Web API中的路由(一)——約定路由


 一.Web API中的路由概念

路由的作用用一句話說明:通過request的uri找到處理該請求的Controller,Action,以及給Action的參數賦值

一些路由的基本概念:

      route:路由規則對象,存放了路由的規則;
    routeCollection:路由規則集合,存放了route對象;
    route template:路由模板,形式和uri接近,用於匹配uri;
    route dictionary:路由字典,找到uri匹配的route template后創建的用於存儲route template中占位符值的字典;
    RouteData:真正存放路由信息的對象,保存了Controller、Action的值等;
    Http method:請求api的方式,如get/post/put/delete等。

web api中默認的路由:

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

   route collection 中的每個 route (路由規則對象)都包含一個路由模板( route template )。Web API的默認路由模板是“api / {controller} / {id}”。在此模板中,“api”是文字路徑段,{controller}和{id}是占位符變量。當Web API框架收到HTTP請求時,它會嘗試將URI與route table中的某個route template進行匹配。如果沒有route匹配,則客戶端收到404錯誤。

二、路由過程

路由的過程有三步:
  1.通過uri匹配到route template
  2.獲取對應的Controller
  3.獲取對應的Action

第一步:通過uri匹配到route template

  路由模板看起來很像uri地址,但是它包含了一些占位符,下邊我們通過 WebApiConfig.cs 添加一個route(路由規則),名字是MyRoute,當沒有controller時,默認的controller時Home;自定義參數id添加了一個約束:id必須是數字。當我們添加下邊的代碼后,routeCollection就多了一個route對象。

config.Routes.MapHttpRoute(
  name: "DefaultApi",
  routeTemplate: "api/{controller}/{id}",
  defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
  name: "MyRoute",
  routeTemplate: "api/{controller}/{action}/{id}",
  //可以給占位符提供默認值
  defaults: new { controller = "Home" },
  //可以給占位符添加約束,只有id是數字時才匹配這個路由規則
  constraints: new { id = @"\d+" }
);

  當框架接受到一個request時,會查找uri匹配的路由模板,找到路由模板后會創建一個 Route Dictionary 對象,這個對象里包含每個占位符的值,key是占位符的名字,值從uri中或者默認值中獲取。這個字典對象存儲在IHttpRouteData對象中。
一個栗子:uri為api/Products/FindProduct/1,匹配成功MyRoute的routeTemplate成功,創建的路由字典中包含了

  controller:Products
  action:FindProduct
  id:1

第二步:獲取Controller

Controller的默認方法很簡單:
  找到路由字典中的controller,在controller的值后天追加“Controller”。如我們路由字典中的controller的值是Products,那么找的Controller就是 Products+"Controller"=ProductsController。

第三步:獲取Action

  獲取Action時,Web API會查看HTTP方法,然后查找名稱以該HTTP方法名稱開頭的action。例如,對於GET請求,Web API會查找以“Get ...”開頭的操作,例如“GetContact”或“GetAllContacts”。此約定僅適用於GET,POST,PUT和DELETE方法。您可以使用控制器上的屬性啟用其他HTTP方法。當找到多個方法符合http method時,匹配參數符合最多的那個。

三、覆蓋默認HttpMethod

3.1  使用HttpMethod特性 

  當我們使用[HttpGet] [HttpPost] [HttpPut] [HttpDelete]特性修飾action時,web api接收到一個請求時,也會按照http method進行查找,如用[HttpGet]修飾action,我們以get的形式訪問http://xxx:xx/Products時,會找到下邊栗子的FindProduct(id)。注意:如果沒有屬性標簽,也不以Http method開頭,那么默認為post。
  一個栗子:

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

3.2  使用AcceptVerbs和NonAction特性 

  如果我們想讓一個方法在多個Http method中匹配,如我們使用get或者post請求時都訪問方法FindProduct(id),怎么去設置呢?可以使用AcceptVervs進行設置,如下設置后當我們使用get或者post請求api/products/都會匹配到方法FindProduct

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

怎么讓controller中的普通方法,不被匹配到呢?只需要在方法上邊添加 [NonAction] 即可

[NonAction]
public string GetStr(Product p){
    return p.Name;
}

小結:以http://xxxx:xx/Products/1 簡單說明webapi中路由過程:我們設定的 Route 都存放的RouteCollection中,當webapi框架到一條request后,通過request的 uri (采用的方法是 routes.MapRoute )匹配route中的 route template ,如果有匹配的話,生成一個 Route Dictionary 對象,這個字典對象中存儲了route template的占位符的值;接下來我們從route dictionary中查找controller值(Products),通過字符串拼接找到處理請求的ProductsController;通過request的 http method (如這里采用的get方法),查找ProductsController中的Action中匹配get的,這時我們找到了GetAllProducts和GetProduct(int id),因為我們傳入有額外的項1,在GetProduct匹配的參數1個,而在GetAllProducts中匹配的參數時0個,按匹配參數最多的進行匹配所有最終匹配的action是GetProduct,最后把額外的1賦值給GetProduct的參數id。一次路由到這里就結束了。


免責聲明!

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



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