ASP.NET Web API属性路由疑问:查询字符串为何匹配GetAll方法?
这事儿核心是Web API的路由匹配逻辑在起作用:
你的GetByBirthdate方法用的路由模板是"{birthdate}",这个模板期望birthdate是URL路径里的一个片段(比如/users/1907-04-19),而不是作为查询字符串参数(也就是?birthdate=xxx这种形式)。
而你的请求URL是localhost/Users?birthdate=1907-04-19&api-version=2.0,路径部分就是/Users,刚好完全匹配GetAll方法的[Route("")]模板(因为RoutePrefix是users,所以完整路径是/users)。Web API在匹配路由时,首先看的是URL路径和路由模板是否匹配,查询参数不会参与路由模板的匹配——它只会在路由匹配到同一个控制器下的多个动作时,用来辅助选择具体调用哪个方法。
所以现在的情况是,路径匹配了GetAll的模板,自然就路由到这个方法了。
有两种常见的方案,看你想要哪种URL风格:
方案1:让birthdate作为查询参数匹配GetByBirthdate
把GetByBirthdate的路由模板改成和GetAll一样的[Route("")],然后利用参数来让Web API区分两个动作:
[RoutePrefix("users")] public class UsersController : ApiController { [ResponseType(typeof(List<User>))] [Route("")] public IHttpActionResult GetAll() { } [Route("")] [ResponseType(typeof(List<User>))] // 明确标记参数来自查询字符串,并且是必填的 public IHttpActionResult GetByBirthdate([FromQuery][Required] DateTime birthdate) { } }
这样当请求URL带birthdate查询参数时,Web API会自动选择GetByBirthdate;不带该参数时,就会调用GetAll。
方案2:保持路径式的birthdate参数
如果你想保留原来的路由模板,那就要修改请求URL,把birthdate放到路径里:
localhost/Users/1907-04-19?api-version=2.0
这样路径部分/users/1907-04-19就会匹配GetByBirthdate的[Route("{birthdate}")]模板,自然就会路由到这个方法了。
内容的提问来源于stack exchange,提问作者user2412672

