第十五节:Asp.Net Core MVC和WebApi路由规则的总结和对比-第二十节
一. Core Mvc
1.傳統路由
Core MVC中,默認會在 Startup類→Configure方法→UseMvc方法中,會有默認路由:routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");?等價于 app.UseMvcWithDefaultRoute();
(1). 參數解析說明
name代表:路由名稱, template代表:路由模板,可以在上面直接賦默認值,defaults代表:路由默認值;constraints代表:路由約束
(2). 多個路由
多個路由默認從上往下解析,注意路由名稱不能相同。
比如: template: "{controller}/{action}/{id?}", 和 template: "{action}/{controller}/{id?}"兩個路由規則共存,那么我既可以通過 https://localhost:44333/Index2/Home 訪問頁面,也可以通過 https://localhost:44333/Home/Index2 訪問頁面
1 //1.默認路由2 //1.1 簡版路由3 {4 routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");5 }6 7 //1.2 路由名稱和多個參數的問題8 {9 routes.MapRoute( 10 name: "default", 11 template: "{controller}/{action}/{id?}", 12 defaults: new { controller = "Home", action = "Index" } 13 ); 14 routes.MapRoute( 15 name: "default2", 16 template: "{action}/{controller}/{id?}", 17 defaults: new { controller = "Home", action = "Index2" } 18 ); 19 }2. 屬性路由
(1).Route[]
Route可以單獨作用Controller,也可以單獨作用于action,當然也可以同時作用。
(前提:注釋掉全局的傳統路由,當然也可以不注釋,因為同時存在的話,屬性路由的優先級高)
測試1:只在控制器上添加 [Route("Home2/{action}")],則可以通過【https://localhost:44333/Home2/Test1】正常訪問.
測試2:只在Test1方法上添加 [Route("{controller}/Test111")], 則可以通過【https://localhost:44333/Home/Test111】正常訪問
標記替換:直接以這種形式[Route("api/[controller]/[action]")]作用于控制器,該控制的匹配規則都將自動適配名稱,該方法普遍用于WebApi上.
代碼如下:
1 [Route("Home2/{action}")]2 public class HomeController : Controller3 {4 5 [Route("{controller}/Test111")]6 public string Test1()7 {8 return "ok1";9 } 10 }(2).Http[Verb]
Http[Verb]只能單獨作用于action.
測試1:只在Test2方法上添加 [HttpGet("{controller}/Test22")],則可以通過【https://localhost:44333/Home/Test22】正常訪問
測試2:只在Test2方法上添加 [HttpGet("{controller}/Test22")]和[HttpGet("{controller}/Test222")],則可以通過【https://localhost:44333/Home/Test22】?和【https://localhost:44333/Home/Test232】正常訪問
代碼如下:
1 public class HomeController : Controller2 {3 [HttpGet("{controller}/Test22")]4 [HttpGet("{controller}/Test222")]5 public string Test2()6 {7 return "ok2";8 }9 10 }(3).多個屬性路由的合并規則
A. Route和Route合并:Route可以同時作用在Controller和action,匹配規則是“疊加”;而且每個上面可以放多個,比如控制器上2個,action上3個,則有2*3=6種組合。
測試:控制器上添加:[Route("Home1/{action}")] 和 [Route("Home2/{action}")],
? ? action上添加:[Route("Test3")]、 [Route("Test33")]、 [Route("Test333")]
可以訪問路徑:https://localhost:44333/Home1/Test3/Test3
https://localhost:44333/Home1/Test3/Test33
https://localhost:44333/Home1/Test3/Test333 (訪問不了,因為action上Route以/開頭)
https://localhost:44333/Home2/Test3/Test3
https://localhost:44333/Home2/Test3/Test33
https://localhost:44333/Home2/Test3/Test333 (訪問不了,因為action上Route以/開頭)
注:action上的屬性路由以 / 或 ~/ 開頭的路由模板不與應用于控制器的路由模板合并。
代碼如下:
1 [Route("Home1/{action}")]2 [Route("Home2/{action}")]3 public class HomeController : Controller4 {5 [Route("Test3")]6 [Route("Test33")]7 [Route("/Test333")]8 public string Test3()9 { 10 return "ok3"; 11 } 12 13 }B. Route和Http[Verb]合并,匹配規則也是“疊加”,而且每個上面可以放多個,比如控制器上2個,action上3個,則有2*3=6種組合。
測試:控制器上添加:[Route("Home1/{action}")] 和 [Route("Home2/{action}")],
? ? ? ? ? ?action上添加:[HttpGet("Test3")]、 [HttpGet("Test33")]、 [HttpGet("Test333")]
可以訪問的路徑和上面的一樣,這里不再做重復測試了。
?
(4).擴展自定義屬性路由
新建類,實現IRouteTemplateProvider接口,繼承Attribute類,然后就通過Template字段來聲明自定義屬性的路由規則了,如ypfAttribute類。
1 /// <summary>2 /// 自定義路由特性3 /// </summary>4 public class ypfAttribute : Attribute, IRouteTemplateProvider5 {6 public string Template => "api/[controller]/[action]";7 8 /// <summary>9 /// 屬性排序 10 /// </summary> 11 public int? Order { get; set; } 12 13 /// <summary> 14 /// 屬性名 15 /// </summary> 16 public string Name { get; set; } 173.傳統路由和屬性路由共存
通常情況下傳統路由服務于Core MVC,屬性路由服務于Restful Api,但如果二者共存的時候,屬性路由的優先級更高,傳統路由失效。
?測試案例:打開傳統路由【1.1】簡版路由,然后在Index方法加[Route("kkk")], 這個時候
(1).要想訪問Index2頁面,走的依舊是傳統路由:https://localhost:44333/Home/Index2
(2).要想訪問Index頁面,只能走屬性路由:https://localhost:44333/kkk
注:這里是把特性加在Index方法上,所以請求地址中不能有控制器名稱哦
?代碼如下:
?
4.區域路由(Area)
前提:必須給區域下的控制器加上特性標注區域名稱!!!如: [Area("A1_Areas")]
方案一:
有幾個區域,則通過MapAreaRoute來添加幾個路由,放在傳統默認路由的前面。
1 //3.1 有幾個區域配置幾個區域路由,并且放在默認路由的前面2 {3 //區域路由4 routes.MapAreaRoute("myAreaRoute1", "A1_Areas", "{area}/{controller}/{action}/{id?}");5 routes.MapAreaRoute("myAreaRoute2", "A2_Areas", "{area}/{controller}/{action}/{id?}");6 7 //默認路由8 routes.MapRoute(9 name: "default", 10 template: "{controller=Home}/{action=Index}/{id?}"); 11 12 }方案二:(推薦!)
利用MapRoute方法,添加一個含{area:exists}的路由,必須放在默認路由的后面!
1 //3.2 單獨配置一個含area的路由,放在默認路由的后面2 {3 4 //默認路由5 routes.MapRoute(6 name: "default",7 template: "{controller=Home}/{action=Index}/{id?}");8 9 //區域路由(要放在默認路由的后面) 10 routes.MapRoute( 11 name: "default2", 12 template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"); 13 }測試:
訪問Home/Index 頁面(上面什么特性不要加),里面的連接可以分別跳轉到A1和A2區域下的頁面。
?
二. Core WebApi
默認情況下WebApi的路由規則是RestFul風格的,而且WebApi項目并沒有全局注冊傳統路由,這種模式很不友好.通常我們有兩類改造方案。
(前提補充:[Route]和[ApiController]要成對出現,可以同時和傳統路由共存,優先級比傳統路由高,但是[ApiController]不能單獨出現,不能單獨和傳統路由共存;而?[Route]可以單獨和全局路由共存)
方案一:全局配置,全局進行改造,在Configure方法中添加規則為:"api/{controller}/{action}/{id?}"和"api/{area:exists}/{controller}/{action}/{id?}"的全局路由和區域路由,則我們就可以通過上述路徑進行訪問了。
1 app.UseMvc(routes =>2 {3 //全局路由4 routes.MapRoute(5 name: "default",6 template: "api/{controller}/{action}/{id?}",7 defaults: new { controller = "Second", action = "Test" });8 9 //區域路由(對應區域下面的控制器一定要加 [Area("")]) 10 routes.MapRoute( 11 name: "default2", 12 template: "api/{area:exists}/{controller}/{action}/{id?}"); 13 14 15 //用于顯示默認訪問,這樣直接打開https://localhost:44387/,就可以直接調用方法了。 16 //routes.MapRoute( 17 // name: "default3", 18 // template: "{controller}/{action}/{id?}", 19 // defaults: new { controller = "Second", action = "Test" }); 20 });
方案二:不需要全局配置,在每個控制器的上面添加 [Route("api/[controller]/[action]")]和[ApiController],也可以達到同樣的目的。
1 [Route("api/[controller]/[action]")]2 [ApiController]3 public class SecondController : ControllerBase4 { 5 [HttpGet]6 public string Test()7 {8 return "ok";9 } 10 [HttpGet] 11 public string Test2() 12 { 13 return "ok2"; 14 } 15 [HttpPost] 16 public string Test3(UserInfor model) 17 { 18 return $"{model.userName}+{model.pwd}"; 19 } 20 }PS:在實際開發中,可以這兩種方案相互結合進行使用。
?
總結
以上是生活随笔為你收集整理的第十五节:Asp.Net Core MVC和WebApi路由规则的总结和对比-第二十节的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [你必须知道的.NET]第十九回:对象创
- 下一篇: 网申信用卡额度和柜台哪个高