WebApi-路由機制

來源:互聯網
上載者:User

標籤:成功   ble   通過   val   預設值   ons   映射   UI   ilo   

一、WebApi路由機制是什嗎?

  路由機制通俗點來說:其實就是WebApi架構將使用者在瀏覽器中輸入的Url地址和路由表中的路由進行匹配,並根據最終匹配的路由去尋找並匹配相應的Controller和Action並執行的一個過程。

從WebApi架構接收到來自外部環境的介面調用請求到指定介面的執行大概需要以下的匹配過程:1、匹配URL路由 2、Controller匹配 3、Action匹配

下面我麼分別對這幾個流程進行詳細說明。

 

二、匹配URL路由

  WebApi架構接收到來自外部的介面請求後,首先將路由表中的路由一條一條和Url地址進行匹配,一旦匹配上則不再繼續往下匹配,如果匹配完了所有路由都未匹配上,則會報404錯誤。

如果成功匹配上指定路由,則架構根據路由的Url模板中指定的Controller的所在位置以及Action的所在位置從使用者請求的Url中提取出將要調用的Controller的名稱以及Action的名稱,當然要被調用的Controller名或者Action名也可能不是從使用者發起的介面調用請求Url中獲得的,因為WebApi中在進行路由配置時提供了參數預設值的配置,也就是說Controller名或者Action名可能來源於路由配置時的預設值。

該流程結束後:WebApi架構將會從使用者請求的介面調用URL中提取出使用者想調用的介面所對應的Controller 、Action 、以及使用者傳給指定Action的參數(即路由資料)等等,

這些資料存放區在了一個字典集合中,這個路由資料字典我們可以在Action方法中通過如下方式獲得:

1 IHttpRouteData routeData = Request.GetRouteData();2 IDictionary<string, object> routeDataValues = routeData.Values;

  這裡需要澄清的幾點的是:

1、URL未匹配上任何路由 和  匹配上了路由但是未找到相應的Controller和Action 是兩個不同的概念,IIS對這兩種情況的響應是不一樣的。

URL未匹配上路由:

  如果使用者請求的介面的地址不能和路由表中的所有路由相匹配,IIS將直接報告404錯誤。

匹配上了路由但未找到相應Controller或Action:

       如果匹配上了路由但是未找到響應的Controller或Action,那麼將報類似如下錯誤:

  MessageDetail節點詳細描述了是 Controller未找到還是 Action未找到。

2、由於路由表中可以配置一條或者多條路由,並且WebApi架構在匹配成功一條路由後將不再繼續往下匹配,也就是說即使此時後面還有路由可以

和當前請求匹配也不會被匹配到,所以請務必注意每條路由的配置順序,否則可能造成意想不到的結果。

如:

 1 public static void Register(HttpConfiguration config) 2 { 3             config.Routes.MapHttpRoute( 4                 name: "TestRoute", 5                 routeTemplate: "{controller}/{action}", 6                 defaults: new { action = "Index" } 7             ); 8             config.Routes.MapHttpRoute( 9               name: "DefaultApi",10               routeTemplate: "api/{controller}/{id}",11               defaults: new { id = RouteParameter.Optional }12             );13 14 }

假設我們此時代碼中包含如下控制器和Action:

 1 public class ValuesController : ApiController 2 { 3         public string Get() 4         { 5             return "value"; 6         } 7         [HttpGet] 8         public object QueryValues(int index) 9         {10             string[] strs = new string[] { "張三", "李四" };11             if (index < 0 || index >= strs.Length)12             {13                 return JsonConvert.SerializeObject(strs);14             }15             return strs[index];16         }17 }

我們在瀏覽器中輸入:http://localhost:16982/api/Values,會發現總是匹配到的是TestRoute這個路由,實際上我們只是想訪問Values中的無參數的Get方法。

事實上,解決這個問題只需要將TestRoute路由的配置放到DefaultApi路由的後面即可。

三、Controller匹配

      經過路由匹配後,架構已經從使用者請求的Url中提取到需要訪問的Controller名、Action名、以及在路由模板中定義的參數所對應的值等等,此時WebApi架構從路由資料字典中擷取出鍵為:controller的值,在這個值的基礎上去找類型名為  Controller名+Controller 結尾的類,此時如果找到相應名稱的Controller類,則Controller匹配成功,但此時僅僅是Controller匹配成功,最終介面能否成功調用還需取決於下一個步驟中的Action匹配。

  Controller的匹配主要由介面:IHttpControllerSelector.SelectController方法來處理的,這個是WebApi架構定義的介面,定義如下:

1 public interface IHttpControllerSelector2 {3     // Methods4     IDictionary<string, HttpControllerDescriptor> GetControllerMapping();5     HttpControllerDescriptor SelectController(HttpRequestMessage request);6 }

  WebApi架構對控制器的匹配進行了預設的實現,類名叫做:DefaultHttpControllerSelector,這個類預設實現了尋找Controller的過程,在DefaultHttpControllerSelector內部通過 

IHttpControllerTypeResolver介面載入出所有的滿足條件的控制器類型,能被載入並尋找的控制器類型必須滿足以下條件:

1、類必須是實現了IHttpController介面

2、必須是public

3、不能是abstract類

4、類名必須以Controller結尾

最終,從這些列表中找出名稱和路由資料中的Controller名同名的Controller類,並建立該類的執行個體對象。

當然如果我們需要有自己的控制器匹配的邏輯,我們也可以對其進行配置,通過在:/App_Start/WebApiConfig.cs類中進行配置,配置方式如下所示:

1     public static class WebApiConfig2     {3         public static void Register(HttpConfiguration config)4         {5             // 這裡我們配置成使用自己寫的匹配控制器的邏輯6          GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new MyHttpControllerSelectory(GlobalConfiguration.Configuration));7         }8     }

雖然WebApi架構給我們提供了匹配控制器行為的擴充點,但是微軟的預設實作類別DefaultHttpControllerSelector基本上可以滿足大多數情境了。

四、Action匹配

   路由機制找到了將要被調用的Controller類後,接下來就是在當前已經被匹配成功的控制器類下找一個合適的Action方法,並對其調用了,Action的具體匹配流程如下:

1、根據使用者調用介面時的請求方式(GET/POST/DELETE/PUT/Head等等)從已經匹配的控制器類中尋找是用於該種請求方式的Action方法,通過該輪匹配可能會匹配出多個合格Action方法。

2、如果路由資料字典中包含鍵為:action的值,那麼表示Action的名稱必須和該字典中的actionName相一致,也就是說只有Action方法的名稱和路由資料字典中的action名匹配的才算再次步驟匹配。(該步驟不一定是必須執行的,取決於被匹配的路由中是否有指定action預留位置)

3、最後一步就是action的參數綁定了,action中的各個參數的值要麼來源於路由Url模板中定義好的參數在Url中提取到的值,要麼來源於QueryString(也就是?後面的參數值),當然這些說的只是.NET中的原生類型(包括:int/double/DateTime/TimeSpan/Guid等等)的綁定。並不包括自訂的複雜類型(如模型類),其實複雜類型的參數值的綁定預設實現方式是從請求報文提中獲得的。

Action的選擇由介面IHttpActionSelector.SelectAction()方法進行實現,WebApi架構對Action的匹配進行了預設的實現,預設實作類別名為:ApiControllerActionSelector,

IHttpActionSelector介面定義如下:

1 public interface IHttpActionSelector2 {3     // Methods4     ILookup<string, HttpActionDescriptor> GetActionMapping(HttpControllerDescriptor controllerDescriptor);5     HttpActionDescriptor SelectAction(HttpControllerContext controllerContext);6 }

  需要說明的是:能作為Action被執行的方法必須滿足以下幾點:

1、必須是public修飾的方法

2、未被[NonAction]特性修飾的方法

3、不是從ApiController類中繼承過來的方法

4、控制器的建構函式,等等也不會被匹配。

Action的匹配我們也可以實現自訂匹配規則,和上面提到的自訂Controller匹配規則的配置方式類似,如下:

1 public static void Register(HttpConfiguration config)2 {3    GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionSelector), new MyApiControllerActionSelector());45 }

 

  本文主要講述了WebApi架構如何將來自使用者的介面調用請求映射到具體的Controller和Action,並對其進行執行的過程,最容易讓人困惑的部分或許還是Action的選擇部分,

後續我們將繼續討論關於Action選擇部分的具體細節以及參數綁定過程。

  

WebApi-路由機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.