ASP.NET Web API中的Routing(路由)


[譯]Routing in ASP.NET Web API

單擊此處查看原文

本文闡述了ASP.NET Web API是如何將HTTP requests路由到controllers的。

如果你對ASP.NET MVC非常的熟悉,那你將感受到Web API routing與MVC routing是非常的相似的。主要的不同點在於Web API選擇action的時候,使用的是HTTP method,並非URI path。當然,你也可以在Web API中使用MVC風格的routing。以下,本文將不出現任何ASP.NET MVC的相關知識。

Routing Tables

在ASP.NET Web API中,一個controller是一個類,用於處理HTTP requests。其中public方法被稱為 action methods 。當Web API框架接收到一個request,它會將這條request路由到對應的一個action。

Web API框架使用了 route table 來決定調用哪一個action。Visual Studio項目模板為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服務,那么必須在HttpSelfHostConfiguration對象中直接設置好routing table。更多詳情,參見Self-Host a Web API

routing table中的每一個入口都包含了一個 route template 。Web API的默認route template是"api/{controller}/{id}"。在這個template中,"api"是不變的路徑段,{controller}和{id}是兩個占位符。

當Web API框架接受到了一個HTTP request,它會嘗試將URI和route table中的route templates進行匹配。如果沒有路由被命中,客戶端將會收到一個404錯誤。

下面的URIs會匹配到默認路由:

/api/contacts
/api/contacts/1
/api/products/gizmo1

下面的URI無法進行匹配,因為它缺少了api段:

/contacts/1

注意:在api路由中使用"api"路徑段的原因是為了避免跟ASP.NET MVC的路由撞在一起。這樣你就可以將"/contacts"匹配到一個MVC controller,將"/api/contacts"匹配到一個Web API controller。當然咯,如果你不喜歡這種約定,你可以去修改默認route table。

一旦一個路由被匹配到,Web API就選擇了對應的controller和action:

  • 為了找到controller,Web API會將"Controller"添加到{controller}變量中。
  • 為了找到action,Web API會根據HTTP method,去action里面找,直到找到一個名稱由那個HTTP method開頭action。例如,一個Get request,Web API會去找一個名為“Get...”的action,比如"GetContact"或"GetAllContacts"。這個約定只對GET、POST、PUT、DELETE方法。你可以在你的controller上使用特性來允許其他的HTTP method,后面會說到這一點。
  • route template中的其他的占位符變量,比如{id},會映射到action的parameters(參數)。

現在看一個例子:

public class ProductsController : ApiController
{
    public void GetAllProducts() { }
    public IEnumerable<Product> GetProductById(int id) { }
    public HttpResponseMessage DeleteProduct(int id){ }
}

下面是是一些可能的HTTP requests,以及將會被調用到的action。

HTTP Method URI Path Action Parameter
Get api/products GetAllProducts (none)
Get api/products/4 GetProductById 4
DELETE api/products/4 DeleteProduct 4
POST api/products (no match)

注意URI中 {id} 部分如果出現,將會被映射到action的 id 參數。在這個例子中,控制器定義了兩個Get method,一個帶有 id 參數,另一個沒有參數。

同時,請注意Post request將會失敗。因為控制器並沒有定義一個"Post..."的方法。

Routing變化

上一節我們說到了ASP.NET Web API的基礎routing機制。本節將會闡述其他的變化形式。

HTTP Methods

你可以使用HttpGet、HttpPut、HttpPost、HttpDelete特性為一個action顯示指定HTTP method,用於替代原本的HTTP methods命名約定。

下面的例子中,FindProduct方法會被Get requests映射到:

public class ProductsController : ApiController
{
    [HttpGet]
    public Product FindProduct(id) {}
}

如果想要為一個action允許多個HTTP methods,或者除了Get、PUT、POST、DELETE之外的HTTP methods,你可以使用AcceptVerbs特性,它提供了一系列的HTTP methods。

public class ProductsController : ApiController
{
    [AcceptVerbs("GET", "HEAD")]
    public Product FindProduct(id) { }

    // WebDAV method
    [AcceptVerbs("MKCOL")]
    public void MakeCollection() { }
}

帶有Action Name的Routing

通過默認route template,Web API使用HTTP method來選擇調用哪個action。不過你也可以新建一個route,將action名字包含進URI中:

routes.MapHttpRoute(
    name: "ActionApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

在這個route template中,{action} 參數對應controller中的action method名字。這種風格的routing,使用特性來指定允許哪一個HTTP methods。例如,假設你的代碼是如下的寫法:

public class ProductsController : ApiController
{
    [HttpGet]
    public string Details(int id);
}

在這種情況下,一個Get request:"api/products/details/1"將會映射到具體的方法。這種routing跟ASP.NET MVC的非常相似,並且可能也是適用於一個RPC-style API的。

你可以通過ActionName特性來重寫action name。在下面的例子中,有兩個actions會被"api/products/thumbnail/id"映射到。一個支持GET,另一個支持POST。

public class ProductsController : ApiController
{
    [HttpGet]
    [ActionName("Thumbnail")]
    public HttpResponseMessage GetThumbnailImage(int id);

    [HttpPost]
    [ActionName("Thumbnail")]
    public void AddThumbnailImage(int id);
}

Non-Actions

為了防止一個方法被當做action來調用,可以使用NonAction特性。這個信號告訴框架此方法不是一個action,即使它匹配到了某一條路由規則。

// Not an action method.
[NonAction]  
public string GetPrivateData() { ... }

其他

本文從全局闡述了routing。更多詳情,參見Routing and Action Selection,它確切地闡述了框架如何去將URI匹配到route,再如何選擇controller,最后如何選擇一個action來調用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM