ASP.NET沒有魔法——ASP.NET MVC 直連路由(特性路由)


  之前對Controller創建的分析中,知道了Controller的創建是有兩個步驟組成,分別是Controller的類型查找以及根據類型創建Controller實例

  在查詢Controller的類型時,實際上是通過RouteData中的Controller名稱命名空間來完成匹配和查找的,而Controller的名稱就根據路由對象中的url模板來獲取,如默認的url模板:"{controller}/{action}/{id}"。以下是根據ControllerName查找Controller類型的方法,需要注意的是,在通過Controller名稱查找之前還有一個判斷,當RouteData不為空且被匹配為直連路由時,會通過另外的邏輯使用RouteData獲取一個Controller類型。代碼如下:

   

  DirectRoute是什么?本章將從以下幾點介紹直連路由相關內容:
  ● 什么是直連路由
  ● 如何在MVC中使用直連路由
  ● 直連路由與約定路由的區別
  ● 為什么使用直連路由

什么是直連路由

  直連路由又稱為特性路由(Attribute Routing),因為它是通過特性的方式將路由的匹配模板直接應用到Action方法上。如下圖代碼中的action需要使用http://XXX/dr/test才能夠正常訪問:

  

  其中Route特性的定義如下:

  

  從其定義可以看出Route特性可以應用在Controller以及Action上。通過Route特性可以直接為action指定路由。

  那么對於程序來說什么是直連路由呢?從最初給出的代碼來看,代碼層面是通過RouteData.HasDirectRouteMatch方法來判斷的,下圖是判斷邏輯,非常簡單僅僅判斷Value中是否包含名稱為“MS_DirectRouteMatches”的Key值。換句話說,RouteData中包含“MS_DirectRouteMatches”這個Key值的就是直連路由。

  

如何在MVC中使用直連路由

  ASP.NET MVC中有一個對路由表的拓展對象RouteCollectionAttributeRoutingExtensions,其定義如下圖所示,它的功能就是將當前應用中使用特性定義的路由注冊到路由表中

  

  所以在注冊路由時加入以下代碼即可:

  

  在項目中添加以下測試代碼:

  

  運行程序后可以看到dr/test以及dr/test2均被添加到路由表中:

  

  並且在對應的路由信息中包含了Controller和action的信息:

  

  

  注:此處添加了三條路由信息,其中一條它的值是一個RouteCollectionRoute類型,就是說該路由表又包含了一個路由表,被包含的這個路由表中的路由信息是該程序中所有被Route特性標記的Action生成的,另外的兩個LinkGenerationRoute也是通過特性生成的路由。換句話說一個特性標記會生成兩條路由信息但為什么一個特性標記會在兩個路由表中都插入路由對象本章節不再深入分析。

  以下內容更新於2017-12-4:

  關於RouteCollectionRoute和LinkGenerationRoute:其中RouteCollectionRoute是一個專門保存特性路由的路由集合(表),在匹配路由時將會調用RouteCollectionRoute.GetRouteData來完成特性路由匹配,但是要注意的是這里的匹配和路由表中的不同,路由表做的僅僅是遍歷每一個路由對象,並調用路由對象的GetRouteData方法,而RouteCollectionRoute除了遍歷匹配外,還對每一個匹配成功的路由對象添加了“MS_DirectRouteMatches”標記

  

  

  

  但是RouteCollectionRoute的GetVirtualPath方法返回的是null,就是說通過RouteCollectionRoute無法對特性路由生成鏈接,所以又為每一個特性路由在路由表中注冊了LinkGenerationRoute專門用於鏈接的生成,但同樣的LinkGenerationRoute不參與路由匹配,它的GetRouteData返回null:

  RouteCollectionRoute的GetVirtualPath方法:

  

  LinkGenerationRoute的GetRouteData方法:

  

  再次感謝 浮雲也是種寂寞 讓我發現了問題。(*^_^*)

  關於如何在直連路由中使用默認值、路由前綴、默認路由、路由約束、直連路由的Area等功能可參考這篇文章:https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/

直連路由與約定路由的區別

  相對於直連路由來說,使用Controller和Action匹配的路由被稱為基於約定的路由,因為請求url中攜帶了約定好的Controller和Action的名稱。它們的區別主要有以下幾點:
  1. 直連路由與約定路由,路由的注冊方式不同,前者通過查找所有Controller類型中是否使用Route特性來創建路由。后者通過在配置文件中自行添加。
  2. 直連路由在注冊時將對應的Controller和Action的信息包含到了Route對象中,而約定的路由是在解析時通過url模板匹配獲得Controller和Action信息。
  3. 當Action被Route特性標記后,Controller的類型查找不再會通過基於約定的路由的Controller類型查找邏輯。
  4. 當Action被Route特性標記后並且項目中使用了基於約定的路由,那么使用基於約定的路由方法是訪問不到被標記的action的,因為查找Action的邏輯中它們兩種路由是分開的:

  

  5. 直連路由請求中的RouteData自動添加了MS_DirectRoute相關的值,如下:

  

為什么使用直連路由

  直連路由最主要的特性就是路由與實際代碼在同一個文件里,這樣在代碼閱讀時更容易將路由與實際的Action進行匹配,另外使用直連路由可以根據實際的需求來“創造”一個更符合需求的url“新約定”,同時也可以避免基於約定的路由對代碼內部實現的暴露。

小結

  本章通過在MVC的源碼中發現兩種不同的Controller、Action處理方式引出了直連路由的概念,實際上這是MVC5中加入的新特性,可以使用特性的方式指定對應的action的路由模板。但要注意的是盡量避免兩種路由方式的混用造成代碼混亂。

 

參考:

  https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/

本文鏈接:http://www.cnblogs.com/selimsong/p/7722988.html 

 ASP.NET沒有魔法——目錄


免責聲明!

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



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