1. 程式人生 > >【asp.net core 系列】4. 更高更強的路由

【asp.net core 系列】4. 更高更強的路由

# 0. 前言 在之前我們介紹了請求通過路由尋找到控制器,以及控制器與檢視的資料流轉。那麼,我們回過頭來,再看看路由的一些其他用法。 # 1. 路由屬性(Route Attribute) 按照英文的直接翻譯,Routing Attribute 的意思是路由屬性,但實際上 Attribute在微軟的官方稱呼是特性。嗯,所以個人覺得Route Attribute應該是特性路由,路由特性。 嗯,暫且甩開稱呼的問題,小夥伴們知道這是一種使用Attribute標記的路由配置方案就行。我們之前瞭解的路由設定都是通過路由表設定的,而Route Attribute則是另外一種方案。 ## 1.1 如何設定 這種方案主要是通過RouteAttribute類來設定的,我們先來看一下這個類是個什麼樣的吧: ```c# [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public class RouteAttribute : Attribute, IRouteTemplateProvider { public RouteAttribute(string template); public string Name { get; set; } public int Order { get; set; } public string Template { get; } } ``` AttributeUsage 這個特性是用來標註特性的適用範圍的,其中`AttributeTargets.Class | AttributeTargets.Method` 表示這個特性是可以設定在類或者方法上的。AllMultiple表示是否允許設定多個,Inherited 表示被該特性標註的類其子類是否也自動繼承了這個特性。 那麼,我們瞭解了RouteAttribute的適用範圍,繼續看這個類,一共有三個屬性: - Name 表示這個路由特性的名稱 - Order 表示啟用順序,值越小,越先被匹配。預設情況下是0 - Template 路由解析模板,也就是在《【asp.net core 系列】2 控制器與路由的恩怨情仇》中介紹的路由表的格式串 介紹了這麼多,我們先來試試看,先拿出來之前文章建立的MvcWeb專案,新建一個控制器: ```c# using Microsoft.AspNetCore.Mvc; namespace MvcWeb.Controllers { public class RouteTestController: Controller { public IActionResult Index() { return View(); } } } ``` 建立對應檢視: > Views > RouteTest > Index.cshtml 在Index.cshtml中隨便寫點內容,然後儲存。 然後,在RouteTestController 新增一個Route特性標記: ```c# [Route("/Route")] public IActionResult Index() { return View(); } ``` 啟動專案,訪問 `http://localhost:5006/Route` 後,如果不出意外可以看到跟下圖類似的介面: ![image-20200603002255361](https://img2020.cnblogs.com/other/1266612/202006/1266612-20200604160607099-78546388.png) 那麼我們試一試通過路由表設定的路徑是否可以訪問: ``` http://localhost:5006/RouteTest ``` ![image-20200603003824041](https://img2020.cnblogs.com/other/1266612/202006/1266612-20200604160607316-1045222256.png) 可以看到提示404,也就是說這個Action無法通過路由表的形式查詢到了。 ## 1.2 設定引數 我們知道所謂的Action其實也是一個方法,而我們通常請求一個網址的時候,網址中也帶有一些查詢引數。所以,這一節我們就介紹一下路由特性(屬性路由)如何設定引數的解析吧。 ### 1.2.1 不做任何操作 在RouteTestController裡新增方法: ```c# [Route("/route/norest")] public IActionResult NoRest(string name) { ViewBag.Name = name; return View(); } ``` 建立對應的View: ```html

@ViewBag.Name

``` 啟動程式,並訪問:`http://localhost:5006/route/norest` ![image-20200603011055468](https://img2020.cnblogs.com/other/1266612/202006/1266612-20200604160607570-1027397260.png) 新增 ?name=test 在上一個請求的後面: ![image-20200603011147525](https://img2020.cnblogs.com/other/1266612/202006/1266612-20200604160607735-2102912531.png) 嘗試變更name的值,可以發現網頁中的值也發生了變化,證明我們可以獲取到這個值。 ### 1.2.2 當做請求目錄的一部分 在上一小節中,沒有對引數做任何操作,以查詢引數的形式傳遞。在這一篇,我們可以把引數設定為請求的一部分,像目錄那樣,修改上一節示例程式碼為: ```c# [Route("/route/norest/{name}/")] public IActionResult NoRest(string name) { ViewBag.Name = name; return View(); } ``` 請求方式: ``` http://localhost:5006/route/norest/1232 ``` ![image-20200603011838964](https://img2020.cnblogs.com/other/1266612/202006/1266612-20200604160607921-1559160210.png) 修改連線中的1232 內容,然後重新整理頁面,就能發現頁面中的值也發生了變化 ### 1.2.3 給引數一個預設值 之前的設定裡我們都預設引數由請求URL獲取,那麼在這裡我們介紹一下給引數一個值: ```c# [Route("/route/norest/{name=demo}/")] public IActionResult NoRest(string name) { ViewBag.Name = name; return View(); } ``` 訪問連線: ``` http://localhost:5006/route/norest/ ``` 可以看見: ![image-20200603014035541](https://img2020.cnblogs.com/other/1266612/202006/1266612-20200604160608118-1563639041.png) 設定為可空,也就是引數可以不傳: ```c# [Route("/route/norest/{name?}/")] public IActionResult NoRest(string name) { ViewBag.Name = name; return View(); } ``` 訪問連線: ``` http://localhost:5006/route/norest/ ``` 可以看到頁面沒有任何顯示: ![image-20200603014235139](https://img2020.cnblogs.com/other/1266612/202006/1266612-20200604160608414-1334477996.png) 正常情況下,如果不對引數設定可空而且引數被我們當做目錄的一部分時,不給值是會提示404。 ## 1.3 路由約束 | 約束 | 示例 | 匹配項示例 | 說明 | | ------------------- | ------------------------------------------- | -------------------------------------- | ------------------------------------------------------------ | | `int` | `{id:int}` | `123456789`, `-123456789` | 匹配任何整數 | | `bool` | `{active:bool}` | `true`, `FALSE` | 匹配 `true` 或 `false`。 不區分大小寫 | | `datetime` | `{dob:datetime}` | `2016-12-31`, `2016-12-31 7:32pm` | 在固定區域性中匹配有效的 `DateTime` 值。 請參閱前面的警告。 | | `decimal` | `{price:decimal}` | `49.99`, `-1,000.01` | 在固定區域性中匹配有效的 `decimal` 值。 請參閱前面的警告。 | | `double` | `{weight:double}` | `1.234`, `-1,001.01e8` | 在固定區域性中匹配有效的 `double` 值。 請參閱前面的警告。 | | `float` | `{weight:float}` | `1.234`, `-1,001.01e8` | 在固定區域性中匹配有效的 `float` 值。 請參閱前面的警告。 | | `guid` | `{id:guid}` | `CD2C1638-1638-72D5-1638-DEADBEEF1638` | 匹配有效的 `Guid` 值 | | `long` | `{ticks:long}` | `123456789`, `-123456789` | 匹配有效的 `long` 值 | | `minlength(value)` | `{username:minlength(4)}` | `Rick` | 字串必須至少為 4 個字元 | | `maxlength(value)` | `{filename:maxlength(8)}` | `MyFile` | 字串不得超過 8 個字元 | | `length(length)` | `{filename:length(12)}` | `somefile.txt` | 字串必須正好為 12 個字元 | | `length(min,max)` | `{filename:length(8,16)}` | `somefile.txt` | 字串必須至少為 8 個字元,且不得超過 16 個字元 | | `min(value)` | `{age:min(18)}` | `19` | 整數值必須至少為 18 | | `max(value)` | `{age:max(120)}` | `91` | 整數值不得超過 120 | | `range(min,max)` | `{age:range(18,120)}` | `91` | 整數值必須至少為 18,且不得超過 120 | | `alpha` | `{name:alpha}` | `Rick` | 字串必須由一個或多個字母字元(`a`-`z`,不區分大小寫)組成。 | | `regex(expression)` | `{ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)}` | `123-45-6789` | 字串必須與正則表示式匹配。 請參閱有關定義正則表示式的提示。 | | `required` | `{name:required}` | `Rick` | 用於強制在 URL 生成過程中存在非引數值 | # 2. 路由統一字首 在第一節中,我們介紹瞭如何使用RouteAttribute為控制器裡的方法標記路由資訊。有時候會出現這樣的一個問題,一個控制器方法裡可能會出現多個方法(Action)。通常情況下,我們要求一個控制器處理的請求應當有一個統一的字首(或者稱之為URL目錄)。 那麼,這種情況我們仍然繼續使用 RouteAttribute,不過與之前不同的是,這次直接在控制器類上標記: ```c# [Route("/Route")] public class RouteCtrTestController: Controller { } ``` 這時候,在方法上如果添加了RouteAttribute,設定的路由資訊如果不是以`/` 開始,則會將該Action的路由配置加到Controller後面。如果是以`/` 開始,則表示該路由是根路由。 如果沒有設定RouteAttribute,則表示當前方法是處理控制器配置的路由的方法。 如果一個控制器裡出現多個未設定RouteAttribute,則會出錯。 示例程式碼如下: ```c# [Route("/Route")] public class RouteCtrTestController: Controller { public int temp{get;set;} public IActionResult Index(int temp) { return Content($"你好{temp}"); } [Route("Demo")] public IActionResult Demo() { return Content($"你好 Demo"); } } ``` # 2. 總結 今天的內容比較短,這裡介紹了一些路由的另一種用法,小夥伴們對此有個瞭解就可以了。下一篇將會到檢視,開始準備帶領大家做一個小專案啦。 > 更多內容煩請關注[我的部落格《高先生小屋》](https://www.attachie.club) ![file](https://img2020.cnblogs.com/other/1266612/202006/1266612-20200604160609024-407284774.png)