ASP.NET Core MVC 從入門到精通之路由

来源:https://www.cnblogs.com/hsiang/archive/2023/04/13/17308420.html
-Advertisement-
Play Games

隨著技術的發展,ASP.NET Core MVC也推出了好長時間,經過不斷的版本更新迭代,已經越來越完善,本系列文章主要講解ASP.NET Core MVC開發B/S系統過程中所涉及到的相關內容,適用於初學者,在校畢業生,或其他想從事ASP.NET Core MVC 系統開發的人員。 經過前幾篇文章... ...


隨著技術的發展,ASP.NET Core MVC也推出了好長時間,經過不斷的版本更新迭代,已經越來越完善,本系列文章主要講解ASP.NET Core MVC開發B/S系統過程中所涉及到的相關內容,適用於初學者,在校畢業生,或其他想從事ASP.NET Core MVC 系統開發的人員。 經過前幾篇文章的講解,初步瞭解ASP.NET Core MVC項目創建,啟動運行,以及ASP.NET Core MVC的命名約定,創建控制器,視圖,模型,接收參數,傳遞數據等內容,今天繼續講解ASP.NET Core MVC 路由等相關內容,僅供學習分享使用。

 

 

什麼是路由?

 

路由是一種機制,主要是用於檢查每一個用戶請求,將用戶請求映射到Action中,這一動作通過路由中間件來實現。ASP.NET Core MVC使用路由中間件來匹配傳入請求的URL並將它們映射到操作(Action方法)。

 

預設路由

 

在通過模板創建ASP.NET Core MVC中,預設會添加路由中間件,並提供一種預設的路由映射規則和約束。

MapControllerRoute 用於創建單個路由。 單個路由命名為 default 路由。 大多數具有控制器和視圖的應用都使用類似 default 路由的路由模板。如下所示:

 1 using Microsoft.AspNetCore.Server.Kestrel.Core;
 2 using System.Text.Encodings.Web;
 3 using System.Text.Unicode;
 4 
 5 var builder = WebApplication.CreateBuilder(args);
 6 
 7 // Add services to the container.
 8 builder.Services.AddControllersWithViews().AddJsonOptions(options =>
 9 {
10     options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
11 });
12 
13 builder.Services.Configure<KestrelServerOptions>(options =>
14 {
15     options.AllowSynchronousIO = true;
16 });
17 
18 var app = builder.Build();
19 
20 // Configure the HTTP request pipeline.
21 if (!app.Environment.IsDevelopment())
22 {
23     app.UseExceptionHandler("/Home/Error");
24     // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
25     app.UseHsts();
26 }
27 
28 app.UseHttpsRedirection();
29 app.UseStaticFiles();
30 //1. 添加路由中間件EndpointRoutingMiddleware
31 app.UseRouting();
32 
33 app.UseAuthorization();
34 
35 //2.為控制器和Action添加一種路由映射規則,包括名稱,規則,約束等
36 app.MapControllerRoute(
37     name: "default",
38     pattern: "{controller=Home}/{action=Index}/{id?}");
39 
40 app.Run();

在上述代碼中,創建預設路由的關鍵代碼如下所示:

1 app.MapControllerRoute(
2     name: "default",
3     pattern: "{controller=Home}/{action=Index}/{id?}");

其中各個屬性說明:

  • name表示路由名稱,預設值為default。
  • pattern 為匹配模板,預設值為"{controller=Home}/{action=Index}/{id?}"。其中預設controller=Home,表示預設值為HomeController,action=Index,表示預設預設值為Index。id後面的?表示為可空類型,可以根據需要來填寫。

 

預設路由示例

 

  • 如:/ 表示controller和action都採用預設值,相當於/Home/Index。
  • 如:/Hello表示只指定了controller,action為預設預設值,相當於/Hello/Index。
  • 如:/Hello/Test/5 根據路由匹配規則,提取出controller=HelloController , action=Test , id =5 。如果剛好存在此controller和action,則匹配導航成功。

創建預設路由的簡便寫法,可通過以下代碼替代上面的app.MapControllerRoute,如下所示:

1 //創建預設傳統路由的簡便寫法
2 app.MapDefaultControllerRoute();

以上是傳統路由的示例。 之所以稱為傳統路由,是因為它為 URL 路徑建立了一個約定:

  • 第一個路徑段 {controller=Home} 映射到控制器名稱。
  • 第二段 {action=Index} 映射到操作名稱。
  • 第三段 {id?} 用於可選 id。 {id?} 中的 ? 使其成為可選。 id 用於映射到模型實體。

此傳統路由映射具有以下特點:

  • 僅基於控制器和操作名稱。
  • 不基於命名空間、源文件位置或方法參數。

使用預設路由進行傳統路由可以創建應用,而無需為每個操作提出新的 URL 模式,有助於簡化代碼。使 UI 更具可預測性。

 

多個路由

 

在實際應用中,可以設置多個路由,為某些特定的需求設置專有路由。設置多個路由,如下所示:

1 //2.為控制器和Action添加一種路由映射規則,包括名稱,規則,約束等
2 app.MapControllerRoute(
3     name: "blog",
4     pattern: "blog/{*article}",
5     defaults: new { controller = "Blog", action = "Article" });
6 
7 app.MapControllerRoute(
8     name: "default",
9     pattern: "{controller=Home}/{action=Index}/{id?}");

在上述代碼中,名稱為blog的路由,雖然採用的是傳統路由,但只用於特定操作。

在創建多個路由時,以下幾點需要註意:

  • blog 路由比 default 路由具有更高的匹配優先順序,因為它最先添加。
  • 路由名稱為路由指定邏輯名稱,使用命名路由可以簡化 URL 創建,在應用程式範圍內必須唯一。
  • 預設情況下,傳統路由依賴於順序。 一般情況下,具有區域的路由應放在路由表中靠前的位置,因為它們比沒有區域的路由更具體。也就是:特殊的在前面,通用的在後面

 

不明確操作

 

如果同一個請求有兩個action都滿足路由終結點的匹配,那麼路由會進行如下處理:

  • 選擇最佳的候選項。
  • 引發異常。

如下代碼,在請求時,會兩個都滿足路由匹配規則:

 1 /// <summary>
 2 /// 請求需要編輯的學生信息
 3 /// </summary>
 4 /// <param name="id"></param>
 5 /// <returns></returns>
 6 public IActionResult Edit(int id)
 7 {
 8     var student = new Student()
 9     {
10         Id = 1,
11         Name = "公子小六",
12         Age = 21,
13         Sex = ""
14     };
15     return View();
16 }
17 
18 /// <summary>
19 /// 編輯後保存學生信息
20 /// </summary>
21 /// <param name="id"></param>
22 /// <param name="student"></param>
23 /// <returns></returns>
24 public IActionResult Edit(int id, Student student)
25 {
26     //保存學生
27     return View();
28 }

那麼路由中間件就會跑出異常,如下所示:

 

 在這種情況下,要解析正確的路由,需要通過Http謂詞來區分,只有當請求為Post時,才會請求Edit(int id,Student student);其他請求時【一般為Get】,匹配Edit(int id)。添加Http謂詞後的代碼如下:

 1 /// <summary>
 2 /// 請求需要編輯的學生信息
 3 /// </summary>
 4 /// <param name="id"></param>
 5 /// <returns></returns>
 6 public IActionResult Edit(int id)
 7 {
 8     var student = new Student()
 9     {
10         Id = 1,
11         Name = "公子小六",
12         Age = 21,
13         Sex = ""
14     };
15     return View();
16 }
17 
18 /// <summary>
19 /// 編輯後保存學生信息
20 /// </summary>
21 /// <param name="id"></param>
22 /// <param name="student"></param>
23 /// <returns></returns>
24 [HttpPost]
25 public IActionResult Edit(int id, Student student)
26 {
27     //保存學生
28     return View();
29 }

 

屬性路由

 

屬性路由一般用於WebAPI,使用一組屬性將操作直接映射到路由模板,將應用功能建模為一組資源。屬性路由使用[Route(template)]標記於controller或action中,示例如下所示:

 1 public class TestController : Controller
 2 {
 3 
 4     [Route("Test1")]
 5     [Route("Test1/Index")]
 6     [Route("Test1/Index/{id?}")]
 7     public IActionResult Index(int id)
 8     {
 9         ViewBag.Id = id;
10         return View();
11     }
12 
13     public IActionResult Test()
14     {
15         return View();
16     }
17 }

運行程式,在瀏覽器中,輸入網址【https://localhost:7116/Test1/Index/10】,如下所示:

 

註意:屬性路由中,也可用標記:[Route("[controller]/[action]")],效果可傳統路由一致。

屬性路由與傳統路由對比

經過以上示例,屬性路由與傳統路由,主要由以下幾點差異:

  •  屬性路由需要更多輸入才能指定路由,屬性路由自定義比較強,更能精準控制路由。
  • 傳統預設路由會更簡潔地處理路由。 
  • 屬性路由優先順序高於傳統路由。對於屬性路由,控制器和操作名稱在操作匹配中不起作用,除非使用標記替換。
  • 屬性路由支持定義多個訪問同一操作的路由,意味著每個路由屬性都與操作方法上的每個路由屬性相結合。
  • 屬性路由支持使用與傳統路由相同的內聯語法,來指定可選參數、預設值和約束。如:[HttpPost("product14/{id:int}")]

 

保留關鍵字

 

在ASP.NET Core MVC項目中,會有一些關鍵字,作為路由參數名稱,如下所示:

  • action
  • area
  • controller
  • handler
  • page

在 Razor 視圖或 Razor 頁面的上下文中保留以下關鍵字:

  • page
  • using
  • namespace
  • inject
  • section
  • inherits
  • model
  • addTagHelper
  • removeTagHelper

一個常見錯誤是使用 page 作為屬性路由的路由參數。 這樣做會導致與 URL 生成不一致和令人困惑的行為。錯誤示例如下所示:

1 public class TestController : Controller
2 {
3     [Route("/articles/{page}")]
4     public IActionResult ListArticles(int page)
5     {
6         return View(page);
7     }
8 }

 

Http謂詞和路由模板

 

在ASP.NET Core MVC項目中,具有以下幾種謂詞,用於區分不同的請求方式:

  • [HttpGet]
  • [HttpPost]
  • [HttpPut]
  • [HttpDelete]
  • [HttpHead]
  • [HttpPatch]

ASP.NET Core 具有以下路由模板:

  • 所有 HTTP 謂詞模板都是路由模板。
  • [Route]

 

混合路由:屬性路由與傳統路由

 

ASP.NET Core 應用可以混合使用傳統路由和屬性路由。 通常,對為瀏覽器提供 HTML 頁的控制器使用傳統路由,對為 API 提供服務 REST 的控制器使用屬性路由。

操作既支持傳統路由,也支持屬性路由。 通過在控制器或操作上放置路由可實現屬性路由。 不能通過傳統路由訪問定義屬性路由的操作,反之亦然。 控制器上的任何路由屬性都會使控制器中的所有操作使用屬性路由。

屬性路由和傳統路由使用相同的路由引擎。

以上就是ASP.NET Core MVC從入門到精通之路由的全部內容,旨在拋磚引玉,一起學習,共同進步。


作者:小六公子
出處:http://www.cnblogs.com/hsiang/
本文版權歸作者和博客園共有,寫文不易,支持原創,歡迎轉載【點贊】,轉載請保留此段聲明,且在文章頁面明顯位置給出原文連接,謝謝。
關註個人公眾號,定時同步更新技術及職場文章


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

-Advertisement-
Play Games
更多相關文章
  • 在工作中,我們會將重要的文檔進行加密,並且設置用戶的訪問許可權,其他外部人員均無法打開,只有獲取該許可權的用戶才有資格打開文檔。此外,限制用戶的使用許可權,極大程度上阻止了那些有意要篡改、拷貝其中內容的人,提高文檔的安全性。與此同時,文檔加密的另一大作用是為了防止丟失,因為可能存在員工出差或離職時,將文檔 ...
  • 聲明 本文章中所有內容僅供學習交流使用,不用於其他任何目的,不提供完整代碼,抓包內容、敏感網址、數據介面等均已做脫敏處理,嚴禁用於商業用途和非法用途,否則由此產生的一切後果均與作者無關! 本文章未經許可禁止轉載,禁止任何修改後二次傳播,擅自使用本文講解的技術而導致的任何意外,作者均不負責,若有侵權, ...
  • Vue3的UI Framework中有Element-Plus、BalmUI、Quasar、PrimeVue、Ant Design Vue等UI Framework. Element-Plus是Element-UI的Vue3版,Element-UI的使用人數的基數較大,Github上的Star數也較 ...
  • 大數據時代,各行各業對數據採集的需求日益增多,網路爬蟲的運用也更為廣泛,越來越多的人開始學習網路爬蟲這項技術,K哥爬蟲此前已經推出不少爬蟲進階、逆向相關文章,為實現從易到難全方位覆蓋,特設【0基礎學爬蟲】專欄,幫助小白快速入門爬蟲,本期為數據存儲。 概述 上期我們介紹到了文件存儲,講到瞭如何將數據存 ...
  • 函數進階 函數的作用域 作用域又可以被稱為命名空間,指變數起作用的範圍。Python變數作用域可以分為四種,分別為局部作用域、嵌套作用域、全局作用域、內置作用域。 | 作用域 | 英文 | | | | | 局部作用域 | Local | | 嵌套作用域 | Enclosing | | 全局作用域 | ...
  • 一、事件背景: 某天凌晨,一陣急促的鈴聲將我從周公那裡拉了過來,接聽電話後,一臉懵逼。 什麼情況?XX後臺宕機了?當日日誌也不列印了,前端發起的請求,都報超時,重啟後又恢復了,不清楚會不會再次宕機。 出現這種情況,我第一時間想的是為什麼是00:00:00宕機?難道後臺嫌我這個大齡程式員睡得早了? 然 ...
  • Java SpringBoot 通過javax.validation.constraints下的註解,實現入參數據自動驗證 如果碰到 `@NotEmpty` 否則不生效,註意看下 `@RequestBody` 前面是否加上了`@Valid` ...
  • 介面 ​ 介面類型是對其它類型行為的抽象和概括,因為介面類型不會和特定的實現細節綁定在一 起,通過這種抽象的方式我們可以讓我們的函數更加靈活和更具有適應能力 介面的特點 可以包含0個或多個方法的簽名 只定義方法的簽名,不包含實現 實現介面不需要顯式的聲明,只需實現相應方法即可 介面實現 ​ 介面里沒 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...