zoukankan      html  css  js  c++  java
  • 第二十节: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 : Controller
     3     {
     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 : Controller
     2     {
     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 : Controller
     4     {
     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, IRouteTemplateProvider
     5     {
     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?}"的全局路由和区域路由,则我们就可以通过上述路径进行访问了。

    Core2.x版本

     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             });

    Core3.x写法

     1   app.UseEndpoints(endpoints =>
     2             {
     3                 //默认路由
     4                 endpoints.MapControllerRoute(
     5                     name: "default",
     6                 pattern: "{controller=Admin}/{action=LoginIndex}/{id?}");
     7                 //pattern: "{controller=Demo}/{action=Index}/{id?}");
     8 
     9                 //区域路由(要放在默认路由的后面)
    10                 //注:必须以特性的形式在对应控制器上加上区域名称 [Area("XXXX")]
    11                 endpoints.MapControllerRoute(
    12                    name: "default2",
    13                    pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
    14             });

    方案二:不需要全局配置,在每个控制器的上面添加 [Route("api/[controller]/[action]")]和[ApiController],也可以达到同样的目的。

     1     [Route("api/[controller]/[action]")]
     2     [ApiController]
     3     public class SecondController : ControllerBase
     4     {   
     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:在实际开发中,可以这两种方案相互结合进行使用。

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    赫夫曼树相关算法
    用栈来实现 括号匹配 字符序列检验
    二叉树的建立和遍历
    数据结构-算术表达式求值
    构造一个单链表L,其头结点指针为head,编写程序实现将L逆置
    单链表的基本操作(C语言)数据结构
    java代码打印杨辉三角
    无标题
    写一个方法,判断给定的数字是偶数还是奇数
    关于生物信息学与R的相关资料和网站
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/11849496.html
Copyright © 2011-2022 走看看