一. 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.1 简版路由
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
} //1.2 路由名称和多个参数的问题
{
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "default2",
template: "{action}/{controller}/{id?}",
defaults: new { controller = "Home", action = "Index2" }
);
}

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上.

代码如下:

     [Route("Home2/{action}")]
public class HomeController : Controller
{ [Route("{controller}/Test111")]
public string Test1()
{
return "ok1";
}
}

(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】正常访问

代码如下:

 public class HomeController : Controller
{
[HttpGet("{controller}/Test22")]
[HttpGet("{controller}/Test222")]
public string Test2()
{
return "ok2";
} }

(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上的属性路由以 / 或 ~/ 开头的路由模板不与应用于控制器的路由模板合并。

代码如下:

     [Route("Home1/{action}")]
[Route("Home2/{action}")]
public class HomeController : Controller
{
[Route("Test3")]
[Route("Test33")]
[Route("/Test333")]
public string Test3()
{
return "ok3";
} }

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类。

      /// <summary>
/// 自定义路由特性
/// </summary>
public class ypfAttribute : Attribute, IRouteTemplateProvider
{
public string Template => "api/[controller]/[action]"; /// <summary>
/// 属性排序
/// </summary>
public int? Order { get; set; } /// <summary>
/// 属性名
/// </summary>
public string Name { get; set; }

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来添加几个路由,放在传统默认路由的前面。

         //3.1 有几个区域配置几个区域路由,并且放在默认路由的前面
{
//区域路由
routes.MapAreaRoute("myAreaRoute1", "A1_Areas", "{area}/{controller}/{action}/{id?}");
routes.MapAreaRoute("myAreaRoute2", "A2_Areas", "{area}/{controller}/{action}/{id?}"); //默认路由
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"); }

方案二:(推荐!)

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

                 //3.2 单独配置一个含area的路由,放在默认路由的后面
{ //默认路由
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"); //区域路由(要放在默认路由的后面)
routes.MapRoute(
name: "default2",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
}

测试:

  访问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版本

          app.UseMvc(routes =>
{
//全局路由
routes.MapRoute(
name: "default",
template: "api/{controller}/{action}/{id?}",
defaults: new { controller = "Second", action = "Test" }); //区域路由(对应区域下面的控制器一定要加 [Area("")])
routes.MapRoute(
name: "default2",
template: "api/{area:exists}/{controller}/{action}/{id?}"); //用于显示默认访问,这样直接打开https://localhost:44387/,就可以直接调用方法了。
//routes.MapRoute(
// name: "default3",
// template: "{controller}/{action}/{id?}",
// defaults: new { controller = "Second", action = "Test" });
});

Core3.x写法

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

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

     [Route("api/[controller]/[action]")]
[ApiController]
public class SecondController : ControllerBase
{
[HttpGet]
public string Test()
{
return "ok";
}
[HttpGet]
public string Test2()
{
return "ok2";
}
[HttpPost]
public string Test3(UserInfor model)
{
return $"{model.userName}+{model.pwd}";
}
}

PS:在实际开发中,可以这两种方案相互结合进行使用。

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

第二十一节:Asp.Net Core MVC和WebApi路由规则的总结和对比的更多相关文章

  1. asp.net core mvc 中间件之路由

    asp.net core mvc 中间件之路由 路由中间件 首先看路由中间件的源码 先用httpContext实例化一个路由上下文,然后把中间件接收到的路由添加到路由上下文的路由集合 然后把路由上下文 ...

  2. ASP.NET Core MVC 配置全局路由前缀

    前言 大家好,今天给大家介绍一个 ASP.NET Core MVC 的一个新特性,给全局路由添加统一前缀.严格说其实不算是新特性,不过是Core MVC特有的. 应用背景 不知道大家在做 Web Ap ...

  3. 【转】ASP.NET Core MVC 配置全局路由前缀

    本文地址:http://www.cnblogs.com/savorboard/p/dontnet-IApplicationModelConvention.html作者博客:Savorboard 前言 ...

  4. asp.net core mvc剖析:路由

    在mvc框架中,任何一个动作请求都会被映射到具体控制器中的方法上,那框架是如何完成这样一个过程的,现在我们就来简单分析下流程. 我们紧跟上面的主题,任何一个请求都会交给处理管道进行处理,那mvc处理的 ...

  5. Pro ASP.NET Core MVC 第6版 第一章

    目录 第一章 ASP.NET Core MVC 的前世今生 ASP.NET Core MVC 是一个微软公司开发的Web应用程序开发框架,它结合了MVC架构的高效性和简洁性,敏捷开发的思想和技术和.N ...

  6. 详解 ASP.NET Core MVC 的设计模式

    MVC 是什么?它是如何工作的?我们来解剖它 在本节课中我们要讨论的内容: 什么是 MVC? 它是如何工作的? 什么是 MVC MVC 由三个基本部分组成 - 模型(Model),视图(View)和控 ...

  7. ASP.NET Core 入门教程 3、ASP.NET Core MVC路由入门

    一.前言 1.本文主要内容 ASP.NET Core MVC路由工作原理概述 ASP.NET Core MVC带路径参数的路由示例 ASP.NET Core MVC固定前/后缀的路由示例 ASP.NE ...

  8. ASP.NET Core MVC的路由参数中:exists后缀有什么作用,顺便谈谈路由匹配机制

    我们在ASP.NET Core MVC中如果要启用Area功能,那么会看到在Startup类的Configure方法中是这么定义Area的路由的: app.UseMvc(routes => { ...

  9. ASP.NET Core 入门笔记4,ASP.NET Core MVC路由入门

    敲了一部分,懒得全部敲完,直接复制大佬的博客了,如有侵权,请通知我尽快删除修改 摘抄自https://www.cnblogs.com/ken-io/p/aspnet-core-tutorial-mvc ...

随机推荐

  1. webwork遍历数组标签

    WebWork中提供了一个<ww:iterator></ww:iterator>标签用于遍历数组. 01 如果数组中是普通类型,比如String.int等类型,可以通过标签中的 ...

  2. 前端之html5和css3

    圆角,透明度,rgba CSS3圆角 设置某一个角的圆角,比如设置左上角的圆角:border-top-left-radius:30px 60px;同时分别设置四个角: border-radius:30 ...

  3. NGINX 配置清单

    以下内容来自 SimulatedGREG/nginx-cheatsheet. 通用设置 端口 listen server { # standard HTTP protocol listen 80; # ...

  4. Redisson实现分布式锁(1)---原理

    Redisson实现分布式锁(1)---原理 有关Redisson作为实现分布式锁,总的分3大模块来讲. 1.Redisson实现分布式锁原理 2.Redisson实现分布式锁的源码解析 3.Redi ...

  5. java基础(12):构造方法、this、super

    1. 构造方法 我们对封装已经有了基本的了解,接下来我们来看一个新的问题,依然以Person为例,由于Person中的属性都被private了,外界无法直接访问属性,必须对外提供相应的set和get方 ...

  6. PHP面试题2019年新浪工程师面试题及答案解析

    一.单选题(共28题,每题5分) 1.以下语句输出的结果是什么? A.3$a\$a3336 B.33\$a3336 C.$a$a\$a3336 D.3$a\$a333$a$a 参考答案:A 答案解析: ...

  7. C++ 赋值运算符'='的重载(浅拷贝、深拷贝)

    01 赋值运算符重载的需求 有时候希望赋值运算符两边的类型可以不匹配,比如:把一个 int 类型变量赋值给一个Complex(复数)对象,或把一个 char* 类型的字符串赋值给一个字符串对象,此时就 ...

  8. Python格式化输出和深浅复制

    字符串的四种拼接方法,常用格式化 deepcopy(深复制) bytes 和 bytearray 的基本用法 字符串拼接 使用 + 格式化字符串 使用join 用单引号内的字符来拼接,参数填一个整体 ...

  9. springboot中http 的get post put delete请求

    组合注解(RequestMapping的变形) @GetMapping = @RequestMapping(method = RequestMethod.GET)@PostMapping = @Req ...

  10. 如何将MagicaVoxel模型导入UE4中(1)

    前言 当初在选择自己项目的美术风格时,由于自己的美术基础实在是太差,所以选择了体素风格来构建(其实还是MagicaVoxel的建模操作很容易上手),但是将自己千辛万苦做好的模型导入至项目中时,出现了这 ...