ASP.NET?Core中MVC模式實現(xiàn)路由一
相關(guān)文章
1.前言
ASP.NET Core MVC使用路由中間件來匹配傳入請求的URL并將它們映射到操作(Action方法)。路由在啟動代碼(Startup.Configure方法)或?qū)傩裕–ontroller Action屬性)中定義。路由描述應(yīng)如何將URL路徑與操作(Action方法)相匹配。它還用于在響應(yīng)中生成送出的URL。
路由操作可以設(shè)置中間件,支持傳統(tǒng)路由、屬性理由(通過在Controller Action上放置理由可實現(xiàn))、多個路由。
2.設(shè)置路由中間件
在Configure方法中,可能會看到與下面類似的設(shè)置路由中間件代碼:
app.UseMvc(routes => { routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
等價于
//默認模版就是 "{controller=Home}/{action=Index}/{id?}" app.UseMvcWithDefaultRoute();
在UseMvc的匿名方法中,MapRoute表示創(chuàng)建單個路由,指定為默認(default)路由、路由模版“{controller=Home}/{action=Index}/{id?}”。
路由模版“{controller=Home}/{action=Index}/{id?}”的意思是可以匹配“/Home/Index/5”的URL路徑。也就是說:
- {controller=Home}將Home定義為默認controller。
- {action=Index}將Index定義為默認action。
- {id?}將id定義為可選參數(shù)。
UseMvc和UseMvcWithDefaultRoute可向中間件管道添加RouterMiddleware的實例。MVC不直接與中間件交互,而是使用路由來處理請求。MVC通過MvcRouteHandler實例連接到路由。 重載UseMvc(Action<IRouteBuilder>) 則允許用戶添加自己的路由,并且還支持屬性路由。UseMvcWithDefaultRoute定義默認路由并支持屬性路由。
3.傳統(tǒng)路由
默認路由:
routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
上述代碼就是一個傳統(tǒng)路由,將這種方式稱為傳統(tǒng)路由的原因在于,它為URL路徑設(shè)立了一個約定:
- 第一個路徑段映射到控制器名稱
- 第二段映射到操作名稱。
- 第三段用于可選id(用于映射到模型實體)。
使用此default路由時,URL路徑/Home/Index映射到HomeController.Index。此映射僅基于控制器和操作(action)名稱,而不基于命名空間、源文件位置或方法參數(shù)。
4.多個路由
4.1定義多個路由
通過對UseMvc匿名方法添加多個路由,這樣做可以定義多個約定或添加專用于特定操作的傳統(tǒng)路由,比如:
app.UseMvc(routes => { //第一個路由 routes.MapRoute("blog", "blog/{*article}",defaults: new { controller = "Blog", action = "Article" }); //第二個路由 routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"); });
第一個路由里{*article}是表示使用catch-all路由參數(shù)來捕獲URL路徑的剩余部分。下面我們通過測試來驗證下:
●"blog/{*article}":
●"blog/{article}":
通過上述測試可以知道,加星號的路由在傳參字符串中加了斜杠依然能夠打開,沒加星號的路由在傳參字符串中加了斜杠就不能打開了。還有一點要注意的是controller.action接收參數(shù)必須跟*后面參數(shù)名稱一致,不然會接收不到參數(shù)值。
4.2區(qū)分操作
當(dāng)controller存在兩個action名稱一致的方法,MVC必須要進行區(qū)分,不然會引發(fā)異常,例如:
public class BlogController : Controller { public IActionResult Edit(int id) {} [HttpPost] public IActionResult Edit(int id, Blog blog) {} }
當(dāng)請求為HTTP POST時MVC會選擇Edit(int, Blog),在Http屬性為任何其他內(nèi)容時選擇 Edit(int)。如果匹配多個路由,而MVC找不到“最佳”路由Action時,則會引發(fā) AmbiguousActionException異常。
5.屬性路由
5.1 屬性路由
屬性路由使用一組屬性將操作(Action)直接映射到路由模板。 在下面的示例中,Configure 方法使用app.UseMvc(),不傳遞任何路由。HomeController將匹配一組URL,這組URL與默認路由{controller=Home}/{action=Index}/{id?}匹配的URL類似:
public class HomeController : Controller { [Route("")] [Route("Home")] [Route("Home/Index")] public IActionResult Index() { return View(); } }
下面我們通過表格來看看每個屬性路由在瀏覽器上打開鏈接是怎樣的效果。
Route Template | Browser | Page |
Route("") | [SERVICE_NAME] | [SERVICE_NAME]/Home/Index |
Route("Home") | [SERVICE_NAME]/Home | |
Route("Home/Index") | [SERVICE_NAME]/Home/Index |
三種屬性路由在瀏覽器上打開鏈接方式都不一樣,但是呈現(xiàn)頁面是一樣的,也就是說三個屬性路由的定義方式都是指向同一個/Home/Index頁面。到這里或許大伙會有疑問,如果我把三個屬性路由模版名稱都改變下,那會能打開同一個頁面么?
[Route("1")] [Route("Home1")] [Route("Home1/Index1")]
上述模版名稱更改了,但是在瀏覽器呈現(xiàn)頁面還是指向/Home/Index的,也就是說,無論屬性路由模版名稱如何更改總能打開對應(yīng)/Home/Index頁面。
5.2 使用 Http[Verb] 屬性的屬性路由
屬性路由還可以使用Http[Verb]屬性,比如HttpPostAttribute。所有這些屬性都可采用路由模板。此示例展示與同一路由模板匹配的兩項操作:
public class BlogController : Controller { [HttpGet("/article/{id}", Name = "Article_List")] public IActionResult Article(string id) { return View(); } }
當(dāng)我們在瀏覽器上輸入[SERVICE_NAME]/article/1時候,通過DEBUG我們可以看到響應(yīng)結(jié)果:
通過響應(yīng)結(jié)果可以知道屬性路由首先將URL與路由屬性定義的路由模板集([HttpGet("/article/{id}", Name = "Article_List")])進行匹配。一旦某個路由模板匹配,就會應(yīng)用IActionConstraint約束來確定可以執(zhí)行的操作。
5.3合并路由
根據(jù)業(yè)務(wù)場景如果我們需要將某個Controller重新命名為以便訪問該Controller下面所有action,那么該如何設(shè)置呢?下面通過示例來演示下:
[Route("homes")] public class HomeController : Controller { [HttpGet("{id}")] public IActionResult Index() { return View(); } }
根據(jù)上述代碼,在HomeController上放置路由屬性([Route("homes")])會使控制器中的所有操作(Action)都使用該屬性路由。也就是說只有URL HTTPGet :[SERVICE_NAME]/homes/1才能訪問Index視圖。這種做法好處是,HomeController下的每個Action操作不用單獨添加Route("homes")屬性,只需要在HomeController外放置一個全局Route("homes")屬性即可應(yīng)用到每個Action去,減少路由屬性重復(fù)。
5.4指定屬性路由的可選參數(shù)、默認值和約束
屬性路由同時也支持使用與傳統(tǒng)路由相同的內(nèi)聯(lián)語法,來指定可選參數(shù)、默認值和約束。下面請看示例:
public class HomeController : Controller { [HttpGet("homes/{id:int}")] public IActionResult Index(int id) { return View(); } }
上述代碼執(zhí)行結(jié)果我們通過表格來看看效果:
Browser | Result status |
[SERVICE_NAME]/homes/1 | 200 |
[SERVICE_NAME]/homes/qwe | 404 |
[HttpGet("homes/{id:int}")]把傳入id參數(shù)值約束為只有數(shù)字才能打開該屬性下視圖,如果傳入是字符串則無法找到該視圖。而更多路由約束模板在這里參閱。
5.4自定義屬性路由
我們可以通過框架自帶的IRouteTemplateProvider接口自定義路由屬性(例如類似[HttpGet]、[Route("homes")]等屬性)。當(dāng)應(yīng)用程序啟動時,MVC會查找控制器類和操作方法上的屬性,并使用實現(xiàn)IRouteTemplateProvider的屬性生成一組初始路由。此部分通過一個簡單的示例說明了如何使用應(yīng)用程序自定義屬性路由:
public class MyControllerAttribute : Attribute, IRouteTemplateProvider { //實現(xiàn)接口的三個屬性,這里的[controller]是一個標(biāo)記替換。 public string Template => "api/[controller]/{action}/{id?}"; public int? Order { get; set; } public string Name { get; set; } }
新建一個路由屬性類自定義屬性路徑,然后在Controller或者Action上放置自定義屬性路由。
public class BlogController : Controller { [MyController()] public IActionResult Article(string id) { return View(); } }
通過執(zhí)行[SERVICE_NAME]/api/Blog/Article/1鏈接時訪問成功,也就是說自定義屬性路由成功。
到此這篇關(guān)于ASP.NET Core中MVC模式實現(xiàn)路由的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
asp.net aspnetpager分頁統(tǒng)計時與實際不符的解決辦法
最近分頁方面根據(jù)實際需要修改了一些函數(shù)2008-11-11asp.net Web站點風(fēng)格切換的實現(xiàn)
Web站點的風(fēng)格切換是很常見、也很受大家歡迎的功能,比如大家熟知的博客園就提供了幾十款風(fēng)格模板供大家選擇。2009-05-05解決.NET?Core企業(yè)微信openapi回調(diào)地址請求不通過的問題
這篇文章介紹了解決.NET?Core企業(yè)微信openapi回調(diào)地址請求不通過的問題,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06ASP.NET MVC中使用log4net的實現(xiàn)示例
這篇文章主要介紹了ASP.NET MVC中使用log4net的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01HttpRequest Get和Post調(diào)用其他頁面的方法
HttpRequest Get和Post調(diào)用其他頁面的方法,需要的朋友可以參考一下2013-03-03國產(chǎn)化中的?.NET?Core?操作達夢數(shù)據(jù)庫DM8的兩種方式(操作詳解)
這篇文章主要介紹了國產(chǎn)化之?.NET?Core?操作達夢數(shù)據(jù)庫DM8的兩種方式,這里提供兩種方式是傳統(tǒng)的DbHelperSQL方式和Dapper?方式,每種方式給大家介紹的非常詳細,需要的朋友可以參考下2022-04-04.NET Core Web APi大文件分片上傳研究實現(xiàn)
這篇文章主要介紹了.NET Core Web APi大文件分片上傳研究實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11