ASP.NET Web API 如何將 HTTP 請求路由到控制器


前言

本文描述了 ASP.NET Web API 如何將 HTTP 請求路由到控制器。

如果你熟悉Asp.Net MVC,Web API的路由與Asp.Net MVC的路由是非常類似的。這主要的區別就是Web API使用的是HTTP方法,而不是URI路徑來選擇Action。你也可以在Web API中使用MVC風格的路由。本文不需要有任何Asp.Net MVC的基礎。

Routing Tables路由表

  在Asp.Net Web API中,一個控制器就是一個處理HTTP請求的類,控制器的public 方法被叫做action方法或者簡單的Aciton。當Web API接收到一個請求的時候,它將這個請求路由到一個Action。

  為了確定那個Action被調用,這個框架使用了一個路由表。Visual Studio中Web API的項目模板會創建一個默認路由:

 config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

這個路由是在WebApiConfig.cs文件中定義的,該文件位於App_Start目錄。

關於WebApiConfig類的更多信息參閱“配置ASP.NET Web API”(暫未實現)

如果你要自己托管(self-host )Web API,你必須直接在HttpSelfHostConfiguration對象上設置路由表。更多信息參閱“自托管Web API"。(暫未實現)

  路由表中的每一個條目都包含一個路由模板。這個Web API默認的路由模版是"api/{controller}/{id}"。在這個模版中,“api”是一個文字式路徑片段,而{controller}和{id}則是占位符變量。

  當Web API框架接收一個HTTP請求時,它會試圖根據路由表中的一個路由模板來匹配其URI。如果無路由匹配,客戶端會接收到一個404(未找到)錯誤。例如,以下URI與這個默認路由的匹配:

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

然而,以下URI不匹配,因為它缺少“api”片段:

  • /contacts/1

在路由中使用“api”的原因是為了避免與ASP.NET MVC的路由沖突。通過這種方式,可以用“/contacts”進入一個MVC控制器,而“/api/contacts”進入一個Web API控制器。當然,如果你不喜歡這種約定,你也可以修改這個默認路由表。

 一旦一個匹配的路由被發現,Web API便會選擇相應的Controller和Action。

  1.為了找到Controller,Web API會把“控制器”加到{controller}變量的值。

  2.為了找到Action,Web API會查找HTTP方法,然后尋找一個名稱以HTTP方法名開頭的方法。例如,對於一個Get請求,Web API會查找一個以“Get…”開頭的動作,如“GetContact”或“GetAllContacts”等。這種約定只應用於GET、POST、PUT和DELETE方法。通過在你的Controller上使用attributes,你可以啟用其他的HTTP方法。稍后我們就會看到一個例子。

  3.路由模版中其他的占位變量,例如{id},將被映射成Action的參數。

 

讓我們來看一個簡單的例子,假設你定義了以下控制器:

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

以下是一些可能的HTTP請求,以及要被調用的每個動作:

注意,URI中的{id}片段如果出現,會被映射成Action的id參數。在這個例子中,這個控制器定義了兩個GET方法,一個帶有id參數的和一個不帶有id參數的。

另外要注意,POST請求是失敗的,因為該控制器未定義“Post…”方法。

Routing Variations路由變化

 上一節描述了ASP.NET Web API基本的路由機制。本小節描述一些變化。

HTTP方法

替代使用HTTP方法的命名約定,你可以明確的為一個Action指定HTTP方法,通過以HttpGet、HttpPost、HttpPut或者HttpDelete屬性來對Action方法進行修飾。

在下列示例中,FindProduct方法被映射到GET請求:

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

允許一個Action對應多個HTTP方法,或者允許除了Get、Put、Post、Delete方法之外的HTTP方法,需要使用AcceptVerbs注解屬性,它以HTTP方法列表作為參數。

復制代碼
public class ProductsController : ApiController
{
    [AcceptVerbs("GET", "HEAD")] 
 public Product FindProduct(id) { } // WebDAV method 
 
         
    [AcceptVerbs("MKCOL")] 
 public void MakeCollection() { }
}
復制代碼

第一個方法:指示該動作接收HTTP的GET和HEAD方法(這個HEAD沒測試過)

第二個方法:WebDAV方法(基於Web的分布式著作與版本控制的HTTP方法,是一個擴展的HTTP方法

MKCOL是隸屬於WebDAV的一個方法,它在URI指定的位置創建集合(WebDAV更沒見過)

通過Action名稱路由

在默認的路由模版中,這個Web API使用HTTP方法去選擇Action。然而,你也可以在URI中創建包含動作名的路由:

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

在這個路由模板中,{action}參數命名了控制器上的動作方法。采用這種風格的路由,需要使用注解屬性來指明所允許的HTTP方法。例如,假設你的控制器已有如下方法:

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

在這種情況下,一個Get請求"api/Products/Details/1"將會映射到這個這個Details方法。這種風格的路由類似於Asp.Net MVC,而且可能與RPC式的API相接近。(RPC風格不太懂,還沒查資料)

你也可以通過使用ActionName注解屬性來覆蓋動作名。在以下例子中,有兩個動作映射到“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

為了防止一個方法被作為一個動作所請求,可以使用NonAction注解屬性。它對框架發出信號:這個方法不是一個動作,,即使它可能與路由規則匹配。


免責聲明!

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



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