1. 程式人生 > >跟我一起學.NetCore之路由的最佳實現

跟我一起學.NetCore之路由的最佳實現

**前言** 路由,這詞絕對不陌生,不管在前端還是後端都經常提到,而這節不說其他,就聊.NetCore的路由;在之前的Asp.Net MVC 中,路由算是面試時必問的考點,可見其重要性,它的主要作用是對映URL,而不需要關注伺服器的物理檔案結構,提高安全性,同時規範了URL請求,有利於搜尋引擎優化;所以在Asp.NetCore中當然也不能缺少,以下說說其應用。 **正文** 在Asp.NetCore中,註冊路由方式有兩種: - 模板路由註冊:適合應用於MVC頁面專案,相對於來說,使用模板的形式更加方便,約定大於配置,統一URL; - 特性路由註冊(RouteAttribute):適合應用於API專案,針對於不同業務路由會進行定製,特性標註顯得更加便捷; 少說話,多擼碼,這裡就建立一個WebAPI專案來進行演示: ![img](https://i.loli.net/2020/09/22/tzyJpNEIoMs78AZ.png) 預設情況下,建立的WebAPI專案是推薦使用特性路由方式進行註冊(MVC預設是使用路由模板方式),當然也可以在Api專案中進行使用模板路由方式註冊,如下: ![img](https://i.loli.net/2020/09/22/DI6NWHietV1Z5ab.png) 當註釋掉特性路由,在註冊終結點時增加路由模板,最終執行時會出現異常,因為用ApiController標識的Controller必須是特性路由,那把ApiController特性也註釋掉,結果就正常運行了,如下: ![img](https://i.loli.net/2020/09/22/zEv2miCuHUoIF8S.png) 這裡其實有一個重要的知識點:路由匹配規則,考慮到小夥伴們之前使用Asp.Net MVC時就用到,先預設小夥伴們瞭解這塊知識(抽時間單獨整理一篇出來);以下內容著重說說特性路由應用和路由約束這塊,因為有關注到接觸的專案中不管是之前的Asp.Net, 還是現在的Asp.NetCore專案,幾乎沒有看到路由約束的應用,而在很多場景,路由約束很有必要,用於消除路由的歧義。 **特性路由應用** 直接在Action上加Route 特性,如下: ![img](https://i.loli.net/2020/09/22/FUrOXuQi9tWcBHj.png) 執行結果如下: ![img](https://i.loli.net/2020/09/22/CENm6cthr9o2sUk.png) 通常為了避免在每個Action中的重複的指定路徑字首,可以將公共部分提取到Controller類上進行Route標識,如下: ![img](https://i.loli.net/2020/09/22/MxNJW4fRDIZsHkV.png) 統一字首之後,執行結果: ![img](https://i.loli.net/2020/09/22/BAtHmudcngKaYis.png) 以上的方式都是將路徑寫成固定的字串,有時候會要求像模板路由中那樣動態替換指定標記([area],[controller],[action] ),通常專案中會如下使用: ![img](https://i.loli.net/2020/09/22/KGXTESveg8trLWa.png) 以上只是簡單說說特性路由的用法,小夥伴們可以根據實際情況進行標註,當然如果有特殊需求,也可以進行自定義路由特性,只要繼承**IRouteTemplateProvider**介面即可,上面標註的Route和HttpGet特性也是繼承於這個介面,把RouteAtrribute的原始碼扒出來參考參考: ```c# namespace Microsoft.AspNetCore.Mvc { // 標識此特性只能在類和方法上使用 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public class RouteAttribute : Attribute, IRouteTemplateProvider { private int? _order; // 建構函式,傳入一個Url模板引數 public RouteAttribute(string template) { Template = template ?? throw new ArgumentNullException(nameof(template)); } public string Template { get; } // 路由執行順序,預設為0 public int Order { get { return _order ?? 0; } set { _order = value; } }