如果framework找到一个匹配的URI,创建一个包含占位符值的字典,key就是这些占位符(不包括大括号),value来自URI或者默认值,这个字典存储在IHttpRouteData对象中。默认值可能是RouteParameter.Optional,此时对应的key/value不会被添加到该字典中。
routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{category}/{id}", defaults: new { category = "all", id = RouteParameter.Optional } );
对于URI"api/products",route dictionary中包括:
- controller:"product"
- category:"all"
对于URI"api/products/toys/123",route directionary中包括:
- controller:"products"
- category:"toys"
- id:"123"
Controller的选择:
- 在route dictionary中找到“controller”
- 取到key的值,和"Controller"组合到一起,然后得到对应的controller的类型名
- 在web api的controller中查找这个类型名的controller
Action的选择:
- action必须匹配HTTP method
- 如果route dictionary存在"action",则action的名字需与之匹配
- 对于action的每个参数,如果参数来自URI,则这个参数名必须能在route dictionary或URI中带的参数中找到【可选参数与复杂类型除外】
- 尽可能匹配多的参数,最好的匹配可能是一个没有参数的方法
routes.MapHttpRoute( name: "ApiRoot", routeTemplate: "api/root/{id}", defaults: new { controller = "products", id = RouteParameter.Optional } ); routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); public class ProductsController : ApiController { public IEnumerable<Product> GetAll() {} public Product GetById(int id, double version = 1.0) {} [HttpGet] public void FindProductsByName(string name) {} public void Post(Product value) {} public void Put(int id, Product value) {} }
HTTP Request:
GET http://localhost:34701/api/products/1?version=1.5&details=1
依据以上原则分析最终选择的action是:GetById