這是本人翻譯的第一篇英文文章,翻譯的還非常不好,大家見諒
原文鏈接:http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api
此文章描述了ASP.NET Web API如何將Http請求路由到controller。
路由表
在ASP.NET Web API中,controller是用來處理HTTP請求的一個類。這個類中用於處理HTTP請求的的公共方法被稱之為action method或者簡稱action。當Web API框架接收到一個請求時,會將這個請求路由到一個action來處理。
ASP.NET Web API框架通過使用路由表來確定哪個action方法被調用。Visual Studio 中的ASP.NET Web API項目模板會創建一個默認的路由:
routes.MapHttpRoute( name: "API Default", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
這個默認路由被定義在App_Start目錄下的WebApiConfig.cs文件中。

關於WebApiConfig類的更多信息,參見Configuring ASP.NET Web API.
路由表中的每一條記錄都包含了一個路由模板。默認的Web API路由模板是"api/{controller}/{id}"。在這個模板中,"api"是固定的值,而{controller}和{id}則僅僅是占位符而已(類似於string.Format方法中的格式化字符串使用{0}占位)。
當Web API框架接收到一個HTTP請求時,它會嘗試使用路由表中的路由模板來匹配請求的URI。如果沒有匹配的模板,客戶端就會接收到一個404錯誤。如下的幾個URI是匹配默認模板的:
- /api/contacts
- /api/contacts/1
- /api/products/gizmo1
但是下面的這個URI是不匹配的,因為它缺少"api"部分
/contacts/1
注意:之所以在路由模板中使用"api"這個固定量是為了避免與ASP.NET MVC路由沖突。在ASP.NET MVC中,你可以使用"/contacts"來匹配一個普通的controller,而使用"/api/contacts"來匹配Web API的controller。當然,如果你不喜歡這種約定,也可以更改默認的路由表。
一旦發現了匹配的路由模板,Web API就會選擇合適的controller和action:
1.選擇controller,Web API會在匹配{controller}占位符的值后面加上"Controller",來查找同名的controller
2.選擇action,Web API會查找以HTTP請求的method開頭的方法。比如,有一個Get請求,那么Web API就會查找controller中以Get開頭的方法,比如"GetContact"或者"GetAllContacts".這種約定僅適用於GET,POST,PUT和DELETE方法,你可以通過在方法上面添加特性來啟用某種HTTP method,我們會在后面展示這個例子。
3.路由模板里的其它占位符,比如{id},會被映射到action的參數列表。
我們先來看一個例子,假設有如下定義的一個controller
public class ProductsController : ApiController { public void GetAllProducts() { } public IEnumerable<Product> GetProductById(int id) { } public HttpResponseMessage DeleteProduct(int id){ } }
下面是一些可能的HTTP請求和會被調用到的action
| HTTP Method | URI Path | Action | Parameter |
| GET | api/products | GetAllPriducts | none |
| GET | api/products/4 | GetPriductById | 4 |
| DELETE | api/products/4 | DeleteProduct | 4 |
| POST | api/products | no match |
注意URI中的{id}部分,如果出現的話,這部分的值將會被映射為action方法的名為id的參數。在這個例子里,controller定義了兩個Get開頭的方法,其中有一個有一個名為id的參數,另外一個無參數。
Route Variations(不知道怎么翻譯,路由變體?)
除了使用命名約定以外,還可通過為action添加HttpGet,HttpPut,HttpPost或者HttpDelete特定來顯示指定該action響應的Http method。
下面的例子中,FindProduct方法會對應到Http的Get請求:
public class ProductsController : ApiController { [HttpGet] public Product FindProduct(id) {} }
為了使一個action可以響應多種HTTP method,或者響應除了GET,PUT,POST,DELETE四種之外的其它HTTP method,可以為action指定AcceptVerbs特性,這個特性可以接受一個Http Method列表。
public class ProductsController : ApiController { [AcceptVerbs("GET", "HEAD")] public Product FindProduct(id) { } // WebDAV method [AcceptVerbs("MKCOL")] public void MakeCollection() { } }
通過名字進行路由(Routing by Action Name)
默認路由模板使用Http method來選擇action,但是你也可以使用action的名字來進行路由。
routes.MapHttpRoute( name: "ActionApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } );
在這個模板中,{action}占位符是controller中action的名字,這種形式的路由模板,通過附加在action之上的特性來確定該action響應哪種Http method,例如,假設controller中有如下的方法
public class ProductsController : ApiController { [HttpGet] public string Details(int id); }
在這個例子中,一個請求“api/products/details/1”的http get請求會被映射到Details方法,這種路由風格類似於ASP.NET MVC的路由風格,而且更適用於RPC-style API(遠程過程調用風格的api?)
通過使用ActionName屬性,我們可以指定特定的action名字,而不使用action的方法名,在下面的例子中,有兩個action都會響應"api/products/thumbnail/id"這個uri,但是分別對應get method和post method:
public class ProductsController : ApiController { [HttpGet] [ActionName("Thumbnail")] public HttpResponseMessage GetThumbnailImage(int id); [HttpPost] [ActionName("Thumbnail")] public void AddThumbnailImage(int id); }
非action方法
對於controller中的方法,我們並不希望都會響應HTTP Method,也就是說controller中可以包含非action的方法,那么這時要給這些方法添加NonAction特性,這樣Web Api框架在進行路由匹配的時候就會忽略這些方法。
// Not an action method. [NonAction] public string GetPrivateData() { ... }
