700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 第十五节:Asp.Net Core MVC和WebApi路由规则的总结和对比-第二十节

第十五节:Asp.Net Core MVC和WebApi路由规则的总结和对比-第二十节

时间:2023-04-06 05:37:07

相关推荐

第十五节: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(15name: "default2",16template: "{action}/{controller}/{id?}",17defaults: 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}")]2public 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}")]3public 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>4public 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; }17

3.传统路由和属性路由共存

通常情况下传统路由服务于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(9name: "default",10template: "{controller=Home}/{action=Index}/{id?}");11 12 }

方案二:(推荐!)

利用MapRoute方法,添加一个含{area:exists}的路由,必须放在默认路由的后面!

1 //3.2 单独配置一个含area的路由,放在默认路由的后面2 {3 4 //默认路由5 routes.MapRoute(6name: "default",7template: "{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?}"的全局路由和区域路由,则我们就可以通过上述路径进行访问了。

1app.UseMvc(routes =>2 {3 //全局路由4 routes.MapRoute(5name: "default",6template: "api/{controller}/{action}/{id?}",7defaults: 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]3public 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:在实际开发中,可以这两种方案相互结合进行使用。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。