.NetCore MVC中的路由(1)路由配置基礎

来源:http://www.cnblogs.com/durow/archive/2016/10/24/5992926.html
-Advertisement-
Play Games

.NetCore MVC中的路由(1)路由配置基礎 0x00 路由在MVC中起到的作用 前段時間一直忙於別的事情,終於搞定了繼續學習.NetCore。這次學習的主題是MVC中的路由。路由是所有MVC框架都會實現的一個組件,核心功能就是根據接收到的Http請求中的Path(對於http://local ...


.NetCore MVC中的路由(1)路由配置基礎

 

0x00 路由在MVC中起到的作用

前段時間一直忙於別的事情,終於搞定了繼續學習.NetCore。這次學習的主題是MVC中的路由。路由是所有MVC框架都會實現的一個組件,核心功能就是根據接收到的Http請求中的Path(對於http://localhost/Home/Index/12?test=555 來說,http是協議,localhost是域,Home/Index/12是Path,test=555是參數)部分,依次和路由規則集合中的規則進行匹配,匹配成功後由對應的Controller中的對應Action進行Http請求的處理。匹配不到則返回404錯誤。

 

大多數MVC框架路由規則的配置都大同小異,一般都是通過模板的方式來配置路由規則。有的還支持在Controller和Action上通過Attribute(Java中叫註解)進行更細粒度的配置。

.NetCore MVC支持通過全局的路由模板配置路由規則,也支持在Controller和Action上通過Attribute進行細粒度的路由配置。下麵先說一下在Startup.cs中配置全局路由規則。

0x01 在Startup.cs中配置路由

所謂的路由的模板就是一串字元串,當接收到Http請求後取出其中的Path部分,和模板進行對照,如果匹配模板則路由到對應的Controller和Action進行處理。我們可以在Startup.cs文件中的Configure方法中,添加MVC功能時進行路由配置,例如:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action}/{id}");
});

其中name為路由規則的名稱,template為路由模板。這也引出了我們第一個概念,路由模板中的變數。

1.路由模板中的變數

在模板"{controller }/{action }/{id}"中,用花括弧括起來的是路由模板中的變數。例如其中變數的作用並不是必須在Path中匹配某個固定的字元串,而是起到一個占位的作用,例如上面的模板就可以匹配由“/”隔開的共三部分的Path,例如a/b/c可以匹配成功。而各個變數的值從Path中對應部分提取出來。例如

Home/Index/12可以匹配,其中controller為Home,action為Index,id為12

Home/Index則匹配失敗,因為只有2部分

Home/Index/12/34同樣匹配失敗,因為超過了3部分。

模板匹配成功後,會根據controller和action提取出的值路由:

Home/Index/12會路由到HomeController的Index方法,變數id為12

Test/Show/ab會路由到TestController的Show方法,變數id為ab

2.變數值得獲取

在Index或Show方法中,我們可以有兩種方法提取變數:

一種是在方法的參數列表中加入和變數相同名稱的參數,MVC會自動從變數列表中尋找並轉換為對應類型:

public IActionResult Index(string id, string controller, string action)
{
    ViewData["Message"] = "id is " + id + ",  controller is " + controller + ",  action is " + action;
    return View();
}

另一種就是從RouteData中取出:

public IActionResult Index()
{
    var controller = RouteData.Values["controller"].ToString();
    var action = RouteData.Values["action"].ToString();
    var id = RouteData.Values["id"].ToString();
    ViewData["Message"] = "id is " + id + ",  controller is " + controller + ",  action is " + action;
    return View();
}

路由模板中的變數名稱是可以自己定義的,但controller和action(包括後面講的area)都是比較特殊的變數。其中controller提取出的值作為Controller的名稱,action提取出的值作為Controller中方法的名稱。為了讓每條路由規則都能夠路由到Controller和Action,在路由模板中都應該出現controller和action變數,但我們也可以給controller和action變數指定預設值,這樣在Path中省略了這部分時會用預設值代替。

3.變數的預設值

由兩種方法可以配置變數的預設值:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id=0}");
});

或者

routes.MapRoute(
    name: "default",
    template: "{controller}/{action}/{id}",
    defaults: new 
    {
        controller = ”Home”,
        action = ”Index”,
        id = 0,
    });

這樣配置後Path中帶有預設值的部分可以省略,省略的規則和C#中帶預設值的參數一樣,例如:

空Path會被路由到HomeController,Index方法

Test會被路由到TestController,Index方法

Test/Show依然會被路由到TestController,Show方法

一般我會用第一種方法配置預設值,更加直觀和方便。但有時候有些需求是第一種方法難以做到的。例如我想給TestController的Show方法配置路由為TestShow,使用第一種方法可以這樣配置:”TestShow/{controller=Test}/{action=Show}”,這樣配置當Path為TestShow時的確可以路由到TestController的Show方法,但當Path為TestShow/Home/Index時會路由到HomeController的Index方法。

使用第二種方法配置:

routes.MapRoute(
    name: "test",
    template: "TestShow",
    defaults: new 
    {
        controller = ”Test”,
        action = ”Show”, 
    });

當Path為TestShow時可以路由到TestController的Show方法,但Path為Test/Home/Index則無法匹配模板。關於細粒度的路由配置更好的方法是給Test方法使用Route特性(Attribute)進行配置,後面會說到。

4.路由規則中的靜態字元

除了使用變數來配置路由模板,還可以使用靜態字元串。靜態字元串可以單獨使用,也可以與變數混合使用。

例如模板為:

”Durow/{controller}/{action}”

Durow/Home/About會路由到HomeController,About方法

Durow/Test/Show會路由到TestController,Show方法

也可以把靜態字元和變數混合起來,例如配置模板為:

”My{controller}/My{action}”

MyHome/MyAbout會被路由到HomeController,About方法

MyTest/MyShow會被路由到TestController,Show方法

5.使用?標記變數可選

除了通過給變數提供預設值使其可選外,也可以使用?把變數標記為可選。例如模板

“{controller}/{action}/{id?}”

其中id為可選變數,這樣配置後

Home/Index和Home/Index/12都會成功匹配。

6.使用*提取Path中剩餘的所有部分

如果一個模板需要匹配包含任意多個部分(Segments)的Path,可以使用*符號指定變數,使用*制定過的變數會把Path中匹配完成後剩餘部分全部提取出來,例如模板:

”{controller}/{action}/{id?}/{*others}”

Home/Index/12/a/b/c/d,會路由到HomeController的Index方法,id為12,others為a/b/c/d

實際上僅從模板匹配的角度來說,上面的模板可以匹配所有的Path。唯一的問題就是匹配後對應的Controller和Action可能不存在。

7.多條路由規則的選擇

實際應用中很可能會配置多條路由規則,當接收到Path時很可能不止一條規則能夠匹配。

最簡單的,我們配置以下兩條模板:

“{controller }/{action =About}”

“{controller }/{action =Index }”

當Path為Home時兩條路由都能匹配,那要怎麼選擇呢?其實很簡單粗暴,就是看哪條路由在前面。也就是說Path一旦成功匹配到模板後就會立即實施路由並忽略後面的模板。對於上面的配置來說Home會被路由到HomeController的About方法。所以在配置路由時一定要註意順序。

0x02 使用Attribute配置路由

除了在Startup.cs中配置全局路由規則外,也可以針對單個Controller和其中的Action配置路由。方法就是在Controller類和Action方法上使用Route特性。例如在TestController的Show方法上使用Route特性:

[Route("TestShow")]
public IActionResult Show()
{
    return View();
}

當Path為TestShow時,即可路由到TestController的Show方法。

上面我們在介紹預設值時提到過,通過全局模板配置:

routes.MapRoute(
    name: "test",
    template: "TestShow",
    defaults: new 
    {
        controller = ”Test”,
        action = ”Show”, 
    });

也可以達到同樣的目的。不過區別在於,使用後一種方法時,如果還有”{controller}/{action}”這樣的模板,除了TestShow外,當Path為Test/Show可以匹配這個模板並路由到TestController的Show方法。而通過在Show方法上配置Route特性後,只有TestShow才可以路由,即使同時存在”{controller}/{action}”這樣的模板,Test/Show也無法路由。

第一次接觸用Route特性配置路由時,我很疑惑路由組件是如何把Path路由到對應的Controller和Action的,後來下了個斷點看了下RouteData對象,發現對於配置了路由的Action方法,其controller為方法所在的Controller的名稱,action為方法的名稱,而且在Route特性配置的路由模板中不能夠使用{controller}變數和{action}變數。這樣就保證了匹配模板的Path總能路由到這個Action。

對於在Controller類上配置的Route特性最終會分別配置到Controller中的每個Action上。例如我們在TestController上配置Route(“TestShow”),實際上就是給每個方法配置了Route(“TestShow"),所以當Path為TestShow時會報錯,提示有兩個action滿足匹配。那麼應當如何給Controller通過Route配置路由呢,可以使用[controller]和[action]。

Route特性中的[controller]和[action]

對於[controller]和[action]我也不知道該怎麼叫,不能叫變數,功能上類似占位符。當我們在Controller類用Route特性配置路由時,如果使用了[controller]和[action],這樣當Route特性給Controller中每個Action配置路由時,[controller]會被替換為Controller名稱,[action]會被替換為Action名稱。舉個例子還是給TestController配置Route特性,配置為Route(“durow/[controller]/[action]”),這樣對於其中的Index方法來說,其路由模板為”durow/Test/Index”,controller為Test,action為Index。而對於Show方法來說路由模板為”durow/Test/Show”,controller為Test,action為Show。前面說過MVC會為每個Action創建一個ActionDescriptor對象存儲這個Action的路由信息。對於配置了Route特性的Action(再重覆一下,給Controller類配置Route特性相當於給Controller中的每個Action配置Route特性),其ActionDescriptor中會有一個AttributeRouteInfo對象,對於未配置Route特性的Action,該對象為空。AttributeRouteInfo中包含了路由模板信息。

 

所以對於上面TestController的Route特性的配置,配置為Route(“durow/Test/[action]”)也能達到同樣的效果。不過使用Route(“durow/[controller]/[action]”)語義更強更通用。

在Route特性中使用變數

在Route特性中配置模板也是可以使用變數的,同樣可以使用?標記變數可選。例如可以給TestController配置Route(“durow/[controller]/[action]/{id?}”)。但需要註意的是Route特性的模板中變數不能使用預設值(包括[controller]和[action]),也不能使用*提取Path所有剩餘部分。

0x03 寫在最後

啰啰嗦嗦居然寫了這麼多,其實實際使用中很可能用不到多麼複雜的路由,一般一條通用規則,一條Area相關的規則就可以了。不過詳細瞭解了路由規則,當以後遇到有些奇葩的特殊需求時能夠有更加開闊的思路。後面講討論一下路由模板中的約束和自定義約束。再後面討論一下使用Areas。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 到許可權了。前面講到了 Linux 中的用戶和用戶主管理,其實它們的本質(或者用戶和用戶組出現的初衷)都是方便許可權管理。許可權管理對於電腦的重要性不言而喻,許可權讓每個用戶能夠安安心心的使用電腦,而不用擔心別的用戶破壞到自己的資源。如果老王手裡有一把你家的鑰匙,你是不是很蛋疼呢,如果鄰居除了老王,還有 ...
  • 先安裝字體管理軟體 將需要安裝的字體放到/usr/share/fonts/chinese/目錄下 如果不存在這個目錄,可以自行創建 修改目錄許可權,以便其他用戶也可以使用 應用更改 註意,某些應用可能需要重啟才能生效 使用下麵的命令可以查看已經安裝的字體 ...
  • 從零開始配置ubuntu 14.04,記錄配置服務的過程,安裝組件如下: - SSH - curl - Git - MongoDB - Node.js - ... ...
  • 1.安裝phpStorm,步驟略 2.安裝xampp: 2.1 我下載的版本為:XAMPP 5.6.24(下載最新版裡面沒有xdebug.so文件) 照步驟安裝。 2.2 安裝成功後,啟動一下,看看是否可以運行,在瀏覽器地址欄輸入localhost,查看是否可以進入到xampp網站 。 2.3 點擊 ...
  • 嗬!沒想到吧!學習 Linux 的第三天,我們已經開始接觸用戶管理,用戶組管理,以及許可權管理這幾個逼格滿滿的關鍵字。這幾個關鍵字對於前端程式猿的我來說真的是很高大上有木有,以前嘗試學 Linux 的時候看到這些名詞總是下意識的跳過不敢看有木有,一提起這幾個名詞馬上腦海中總是升騰起無限的崇拜有木有!今 ...
  • 文檔目錄 本節內容: 實體類 聚合根類 領域事件 約定的介面 審計 軟刪除 活躍/消極 實體 實體變化事件 IEntity 介面 領域事件 審計 軟刪除 活躍/消極 實體 實體是DDD一個核心的概念。Eric Evans是這麼描述的:“一個對象根本上不是按它的特性定義的,而是按一個線程的連續性和身份 ...
  • 在做項目的時候,需要輸出資料庫操作的耗時,自己寫了個方法。老大看到後,奇怪我為什麼不用現成的。才知道有StopWatch這個類。 屬性 名稱說明 Elapsed 獲取當前實例測量得出的總運行時間。 ElapsedMilliseconds 獲取當前實例測量得出的總運行時間(以毫秒為單位)。 Elaps ...
  • mvc 碰到 從客戶端(Msg=&quot;...=&quot;pc}oDGY1&lt;h&quot;)中檢測到有潛在危險的 Reque...&quot;)中檢測到有潛在危險的 Request.QueryString 具體參數值 pc}oDGY1<h 引起的錯誤 從網上查在方法前加 [Validat ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...