第十五节: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; }
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(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:在实际开发中,可以这两种方案相互结合进行使用。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438263.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第四节:Task的启动的四种方式以及Task、TaskFactory的线程等待和线程延续的解决方案

一. 背景 揭秘&#xff1a; 在前面的章节介绍过&#xff0c;Task出现之前&#xff0c;微软的多线程处理方式有&#xff1a;Thread→ThreadPool→委托的异步调用&#xff0c;虽然也可以基本业务需要的多线程场景&#xff0c;但它们在多个线程的等待处理方面、资源占用方面、线程…

第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

一. 整体说明 揭秘&#xff1a; 通过F12查看Task类的源码(详见下面的截图)&#xff0c;发现Task类的构造函数有有一个参数为&#xff1a;TaskCreationOptions类型&#xff0c;本章节可以算作是一个扩展章节&#xff0c;主要就来研究TaskCreationOptions类的作用。 该类主要用来…

第六节:深入研究Task实例方法ContinueWith的参数TaskContinuationOptions

一. 整体说明 揭秘&#xff1a; 该章节的性质和上一个章节类似&#xff0c;也是一个扩展的章节&#xff0c;主要来研究Task类下的实例方法ContinueWith中的参数TaskContinuationOptions。 通过F12查看TaskContinuationOptions的源码&#xff0c;知道主要有这么几个参数&#xf…

第七节:利用CancellationTokenSource实现任务取消和利用CancellationToken类检测取消异常。

一. 传统的线程取消 所谓的线程取消&#xff0c;就是线程正在执行的过程中取消线程任务。 传统的线程取消&#xff0c;是通过一个变量来控制&#xff0c;但是这种方式&#xff0c;在release模式下&#xff0c;被优化从cpu高速缓存中读取&#xff0c;而不是从内存中读取&#xf…

第八节:Task的各类TaskTResult返回值以及通用线程的异常处理方案。

一. Task的各种返回值-Task<TResult> PS&#xff1a; 在前面章节&#xff0c;我们介绍了Task类开启线程、线程等待、线程延续的方式&#xff0c;但我们并没有关注这些方式的返回值&#xff0c;其实他们都是有返回值的Task<TResult>&#xff0c;然后可以通过Task的…

第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)

一. 并行编程 1. 区分串行编程和串行编程 ①. 串行编程&#xff1a;所谓的串行编程就是单线程的作用下&#xff0c;按顺序执行。(典型代表for循环 下面例子从1-100按顺序执行) ②. 并行编程&#xff1a;充分利用多核cpu的优势&#xff0c;同时开启多个线程并行执行。(典型代表…

第十节:利用async和await简化异步编程模式的几种写法

一. async和await简介 PS&#xff1a;简介 1. async和await这两个关键字是为了简化异步编程模型而诞生的&#xff0c;使的异步编程更简洁&#xff0c;它本身并不创建新线程&#xff0c;但在该方法内部开启多线程&#xff0c;则另算。 2. 这两个关键字适用于处理一些文件IO操作。…

第十一节:深究用户模式锁的使用场景(异变结构、互锁、旋转锁)

一. 锁机制的背景介绍 本章节&#xff0c;将结合多线程来介绍锁机制&#xff0c; 那么问题来了&#xff0c;什么是锁呢&#xff1f; 为什么需要锁&#xff1f; 为什么要结合多线程来介绍锁呢&#xff1f;锁的使用场景又是什么呢&#xff1f; DotNet中又有哪些锁呢&#xff1f; …

第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)

一. 监视锁(Monitor和lock) 1. Monitor类&#xff0c;限定线程个数的一把锁&#xff08;Synchronized lock是他的语法糖&#xff09;&#xff0c;两个核心方法&#xff1a; Enter&#xff1a;锁住某个资源。 Exit&#xff1a;退出某一个资源。 测试案例&#xff1a;开启5个线…

第十四节: 介绍四大并发集合类并结合单例模式下的队列来说明线程安全和非安全的场景及补充性能调优问题。

一. 四大并发集合类 背景&#xff1a;我们目前使用的所有集合都是线程不安全的 。 A. ConcurrentBag&#xff1a;就是利用线程槽来分摊Bag中的所有数据&#xff0c;链表的头插法,0代表移除最后一个插入的值. (等价于同步中的List) B. ConcurrentStack&#xff1a;线程安全的St…

第十五节:深入理解async和await的作用及各种适用场景和用法

一. 同步VS异步 1. 同步 VS 异步 VS 多线程 同步方法&#xff1a;调用时需要等待返回结果&#xff0c;才可以继续往下执行业务 异步方法&#xff1a;调用时无须等待返回结果&#xff0c;可以继续往下执行业务 开启新线程&#xff1a;在主线程之外开启一个新的线程去执行业…

@PostConstruct注解

PostConstruct是Java自己的注解. PostConstruct该注解被用来修饰一个非静态的void()方法. PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次. PostConstruct在构造函数之后执行,init()方法之前执行. 执行顺序 Constructor >> Autow…

springCloud五大组件--Gateway

SpringCloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。 Spring Cloud Gateway 的目标&#…

多线程篇(被替换)

一. 背景 在刚接触开发的头几年里&#xff0c;说实话&#xff0c;根本不考虑多线程的这个问题&#xff0c;貌似那时候脑子里也有没有多线程的这个概念&#xff0c;所有的业务都是一个线程来处理&#xff0c;不考虑性能问题&#xff0c;当然也没有考虑多线程操作一条记录存在的并…

springCloud五大组件--Eureka

Spring Cloud 支持了 Zookeeper、Consul 和 Eureka&#xff0c;官方推荐 Eureka。 C(一致性)A(高可用)P(分区容错)理论&#xff0c;Eureka的选择就是放弃C&#xff0c;选择AP。 Eureka 采用纯 Java 实现&#xff0c;除实现了注册中心基本的服务注册和发现之外&#xff0c;极大…

.NET异步程序设计之任务并行库

目录 1.简介2.Parallel类 2.0 Parallel类简介2.1 Parallel.For()2.2 Parallel.ForEach()2.3 Parallel.Invoke()2.4 补充&#xff1a;线程安全集合3.Task类 3.0 Task类简介3.1 创建无返回值的Task任务3.2 创建有返回值的Task任务3.3 为Task添加延续任务3.4 Task.Delay3.5 Task对…

Mysql主从延时解决办法

1.忍受大法 第一种解决办法&#xff0c;很简单&#xff0c;无他&#xff0c;不管他&#xff0c;没有读到也没事。这时业务不需要任何改造&#xff0c;你好&#xff0c;我好&#xff0c;她也好~ 如果业务对于数据一致性要求不高&#xff0c;我们就可以采用这种方案。 2.数据同…

关于C#程序的单元测试

目录 1.单元测试概念2.单元测试的原则3.单元测试简单示例4.单元测试框架特性标签5.单元测试中的断言Assert6.单元测试中验证预期的异常7.单元测试中针对状态的间接测试8.单元测试在MVC模式中的实现8.单元测试相关参考9.示例源代码下载 志铭-2020年1月23日 11:49:41 1.单元测试…

NuGet是什么?理解与使用(上)

如果你了解python&#xff0c;那么它类似pip。 如果你了解nodejs&#xff0c;那么它类似npm。 如果你了解ruby&#xff0c;那么它类似gem。 对&#xff0c;它就是一个包&#xff08;package&#xff09;管理平台&#xff0c;确切的说是 .net平台的包管理工具&#xff0c;它提…

NuGet是什么?理解与使用(下)

本篇将回答下面几个问题&#xff1a; 如何解读NuGet Gallery上的包信息&#xff1f;如何上传NuGet包到NuGet Gallery&#xff1f;如何安装本地NuGet包&#xff1f;NuGet包的内容文件与目录结构&#xff1f; 如果你没看过上篇那么它在这里&#xff1a; 6号咸鱼&#xff1a;NuG…