隨著技術的發展,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]")],效果可傳統路由一致。
屬性路由與傳統路由對比
經過以上示例,屬性路由與傳統路由,主要由以下幾點差異:
- 屬性路由需要更多輸入才能指定路由,屬性路由自定義比較強,更能精準控制路由。
- 傳統預設路由會更簡潔地處理路由。
- 屬性路由優先順序高於傳統路由。對於屬性路由,控制器和操作名稱在操作匹配中不起作用,除非使用標記替換。
- 屬性路由支持定義多個訪問同一操作的路由,意味著每個路由屬性都與操作方法上的每個路由屬性相結合。
- 屬性路由支持使用與傳統路由相同的內聯語法,來指定可選參數、預設值和約束。如:[
保留關鍵字
在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/
本文版權歸作者和博客園共有,寫文不易,支持原創,歡迎轉載【點贊】,轉載請保留此段聲明,且在文章頁面明顯位置給出原文連接,謝謝。
關註個人公眾號,定時同步更新技術及職場文章