(8)ASP.NET Core 中的MVC路由一
1.前言
ASP.NET Core MVC使用路由中间件来匹配传入请求的URL并将它们映射到操作(Action方法)。路由在启动代码(Startup.Configure方法)或属性(Controller Action属性)中定义。路由描述应如何将URL路径与操作(Action方法)相匹配。它还用于在响应中生成送出的URL。
路由操作可以设置中间件,支持传统路由、属性理由(通过在Controller Action上放置理由可实现)、多个路由。
2.设置路由中间件
在Configure方法中,可能会看到与下面类似的设置路由中间件代码:
app.UseMvc(routes =>
{
routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
});
等价于
//默认模版就是 "{controller=Home}/{action=Index}/{id?}"
app.UseMvcWithDefaultRoute();
在UseMvc的匿名方法中,MapRoute表示创建单个路由,指定为默认(default)路由、路由模版“{controller=Home}/{action=Index}/{id?}”。
路由模版“{controller=Home}/{action=Index}/{id?}”的意思是可以匹配“/Home/Index/5”的URL路径。也就是说:
●{controller=Home}将Home定义为默认controller。
●{action=Index}将Index定义为默认action。
●{id?}将id定义为可选参数。
UseMvc和UseMvcWithDefaultRoute可向中间件管道添加RouterMiddleware的实例。MVC不直接与中间件交互,而是使用路由来处理请求。MVC通过MvcRouteHandler实例连接到路由。 重载UseMvc(Action<IRouteBuilder>) 则允许用户添加自己的路由,并且还支持属性路由。UseMvcWithDefaultRoute定义默认路由并支持属性路由。
3.传统路由
默认路由:
routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
上述代码就是一个传统路由,将这种方式称为传统路由的原因在于,它为URL路径设立了一个约定:
●第一个路径段映射到控制器名称
●第二段映射到操作名称。
●第三段用于可选id(用于映射到模型实体)。
使用此default路由时,URL路径/Home/Index映射到HomeController.Index。此映射仅基于控制器和操作(action)名称,而不基于命名空间、源文件位置或方法参数。
4.多个路由
4.1定义多个路由
通过对UseMvc匿名方法添加多个路由,这样做可以定义多个约定或添加专用于特定操作的传统路由,比如:
app.UseMvc(routes =>
{
//第一个路由
routes.MapRoute("blog", "blog/{*article}",defaults: new { controller = "Blog", action = "Article" });
//第二个路由
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
第一个路由里{*article}是表示使用catch-all路由参数来捕获URL路径的剩余部分。下面我们通过测试来验证下:

●"blog/{*article}":

●"blog/{article}":

通过上述测试可以知道,加星号的路由在传参字符串中加了斜杠依然能够打开,没加星号的路由在传参字符串中加了斜杠就不能打开了。还有一点要注意的是controller.action接收参数必须跟*后面参数名称一致,不然会接收不到参数值。
4.2区分操作
当controller存在两个action名称一致的方法,MVC必须要进行区分,不然会引发异常,例如:
public class BlogController : Controller
{
public IActionResult Edit(int id) {}
[HttpPost]
public IActionResult Edit(int id, Blog blog) {}
}
当请求为HTTP POST时MVC会选择Edit(int, Blog),在Http属性为任何其他内容时选择 Edit(int)。如果匹配多个路由,而MVC找不到“最佳”路由Action时,则会引发 AmbiguousActionException异常。
5.属性路由
5.1 属性路由
属性路由使用一组属性将操作(Action)直接映射到路由模板。 在下面的示例中,Configure 方法使用app.UseMvc(),不传递任何路由。HomeController将匹配一组URL,这组URL与默认路由{controller=Home}/{action=Index}/{id?}匹配的URL类似:
public class HomeController : Controller
{
[Route("")]
[Route("Home")]
[Route("Home/Index")]
public IActionResult Index()
{
return View();
}
}
下面我们通过表格来看看每个属性路由在浏览器上打开链接是怎样的效果。
|
Route Template |
Browser |
Page |
|
Route("") |
[SERVICE_NAME] |
[SERVICE_NAME]/Home/Index |
|
Route("Home") |
[SERVICE_NAME]/Home |
|
|
Route("Home/Index") |
[SERVICE_NAME]/Home/Index |
三种属性路由在浏览器上打开链接方式都不一样,但是呈现页面是一样的,也就是说三个属性路由的定义方式都是指向同一个/Home/Index页面。到这里或许大伙会有疑问,如果我把三个属性路由模版名称都改变下,那会能打开同一个页面么?
[Route("")]
[Route("Home1")]
[Route("Home1/Index1")]
上述模版名称更改了,但是在浏览器呈现页面还是指向/Home/Index的,也就是说,无论属性路由模版名称如何更改总能打开对应/Home/Index页面。
5.2 使用 Http[Verb] 属性的属性路由
属性路由还可以使用Http[Verb]属性,比如HttpPostAttribute。所有这些属性都可采用路由模板。此示例展示与同一路由模板匹配的两项操作:
public class BlogController : Controller
{
[HttpGet("/article/{id}", Name = "Article_List")]
public IActionResult Article(string id)
{
return View();
}
}
当我们在浏览器上输入[SERVICE_NAME]/article/1时候,通过DEBUG我们可以看到响应结果:

通过响应结果可以知道属性路由首先将URL与路由属性定义的路由模板集([HttpGet("/article/{id}", Name = "Article_List")])进行匹配。一旦某个路由模板匹配,就会应用IActionConstraint约束来确定可以执行的操作。
5.3合并路由
根据业务场景如果我们需要将某个Controller重新命名为以便访问该Controller下面所有action,那么该如何设置呢?下面通过示例来演示下:
[Route("homes")]
public class HomeController : Controller
{
[HttpGet("{id}")]
public IActionResult Index()
{
return View();
}
}
根据上述代码,在HomeController上放置路由属性([Route("homes")])会使控制器中的所有操作(Action)都使用该属性路由。也就是说只有URL HTTPGet :[SERVICE_NAME]/homes/1才能访问Index视图。这种做法好处是,HomeController下的每个Action操作不用单独添加Route("homes")属性,只需要在HomeController外放置一个全局Route("homes")属性即可应用到每个Action去,减少路由属性重复。
5.4指定属性路由的可选参数、默认值和约束
属性路由同时也支持使用与传统路由相同的内联语法,来指定可选参数、默认值和约束。下面请看示例:
public class HomeController : Controller
{
[HttpGet("homes/{id:int}")]
public IActionResult Index(int id)
{
return View();
}
}
上述代码执行结果我们通过表格来看看效果:
|
Browser |
Result status |
|
[SERVICE_NAME]/homes/1 |
200 |
|
[SERVICE_NAME]/homes/qwe |
404 |
[HttpGet("homes/{id:int}")]把传入id参数值约束为只有数字才能打开该属性下视图,如果传入是字符串则无法找到该视图。而更多路由约束模板在这里参阅。
5.4自定义属性路由
我们可以通过框架自带的IRouteTemplateProvider接口自定义路由属性(例如类似[HttpGet]、[Route("homes")]等属性)。当应用程序启动时,MVC会查找控制器类和操作方法上的属性,并使用实现IRouteTemplateProvider的属性生成一组初始路由。此部分通过一个简单的示例说明了如何使用应用程序自定义属性路由:
public class MyControllerAttribute : Attribute, IRouteTemplateProvider
{
//实现接口的三个属性,这里的[controller]是一个标记替换。
public string Template => "api/[controller]/{action}/{id?}";
public int? Order { get; set; }
public string Name { get; set; }
}
新建一个路由属性类自定义属性路径,然后在Controller或者Action上放置自定义属性路由。
public class BlogController : Controller
{
[MyController()]
public IActionResult Article(string id)
{
return View();
}
}
通过执行[SERVICE_NAME]/api/Blog/Article/1链接时访问成功,也就是说自定义属性路由成功。
(8)ASP.NET Core 中的MVC路由一的更多相关文章
- (9)ASP.NET Core 中的MVC路由二
1.URL生成 MVC应用程序可以使用路由的URL生成功能,生成指向操作(Action)的URL链接. IUrlHelper 接口用于生成URL,是MVC与路由之间的基础部分.在控制器.视图和视图组件 ...
- 在 Asp.Net Core 中安装 MVC
在 ASP.NET Core 中安装 MVC 到目前为止,我们在本系列视频中使用的 ASP.NET Core 项目是使用“空”项目模板生成的.目前这个项目没有设置和安装 MVC. 两个步骤学会在 AS ...
- ASP.NET Core中使用自定义路由
上一篇文章<ASP.NET Core中使用默认MVC路由>提到了如何使用默认的MVC路由配置,通过这个配置,我们就可以把请求路由到Controller和Action,通常情况下我们使用默认 ...
- asp.net core 系列 5 MVC框架路由(上)
一. 概述 介绍asp.net core路由时,我初步想了下,分几篇来说明. 路由的知识点很多,参考了官方文档提取出一些重要的知识点来说. 在ASP.NET Core中是使用路由中间件来匹配传 ...
- ASP.NET Core中使用自定义MVC过滤器属性的依赖注入
除了将自己的中间件添加到ASP.NET MVC Core应用程序管道之外,您还可以使用自定义MVC过滤器属性来控制响应,并有选择地将它们应用于整个控制器或控制器操作. ASP.NET Core中常用的 ...
- 如何在ASP.NET Core中构造UrlHelper,及ASP.NET Core MVC路由讲解
参考文章: Unable to utilize UrlHelper 除了上面参考文章中介绍的方法,其实在ASP.NET Core MVC的Filter拦截器中要使用UrlHelper非常简单.如下代码 ...
- 在ASP.NET Core中构建路由的5种方法
原文链接 :https://stormpath.com/blog/routing-in-asp-net-core 在ASP.NET Core中构建路由的5种方法 原文链接 :https://storm ...
- C#调用接口注意要点 socket,模拟服务器、客户端通信 在ASP.NET Core中构建路由的5种方法
C#调用接口注意要点 在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用, 所以首先需要通过调用登录接口来保存c ...
- ASP.NET Core 中的SEO优化(3):自定义路由匹配和生成
前言 前两篇文章主要总结了CMS系统两个技术点在ASP.NET Core中的应用: <ASP.NET Core 中的SEO优化(1):中间件实现服务端静态化缓存> <ASP.NET ...
随机推荐
- centos7.2下安装python3.6.5
yum groupinstall 'Development Tools' 出现错误 系统 centos 7.3 使用命令 yum groupinstall 'Development Tools' 出现 ...
- ansible自动化运维04
ansible playbook ansible-playbook命令格式: ansible-playbook [option] filename(剧本名字) ansible-playbook 命 ...
- shell 脚本中 while 只执行一次
实例代码 while read line ; do ssh -p20002 $line -o StrictHostKeyChecking=no xxxxxxxxx done < ip.txt w ...
- 通过vjudge刷Uva的题目(解决Uva网站打开慢的问题)
最近在跟着算法竞赛入门经典刷题,发现Uva网站打开超级慢,进个主页面都需要好几秒.后来发现可以通过vjudge网站刷Uva的题目,很是方便,在这mark一下,顺便做一下推荐. vjudge网址:htt ...
- Nginx反向代理服务器的安装与配置
Nginx反向代理服务器的安装与配置 时间:10月19日 Nginx反向代理有不少需要我们解决的问题,其中有不少问题是基于安装上的问题,在安装完成后的相关调试也让很多人头疼不已.下面就向大家介绍有关于 ...
- stm32定时器频率采样的方式
频率采样方法通常采样定时器的计数方法,在stm32中,输入捕捉模式,PWM输入模式,都是可以测试外部信号频率采样的.1.输入捕捉模式需要频繁的进中断,这个方式不太好的.如果一定要用,那么就软件上处理一 ...
- Comet OJ 夏季欢乐赛 烤面包片
烤面包片 https://cometoj.com/contest/59/problem/C?problem_id=2698 题目描述 鸡尾酒最喜欢吃东北的烤面包片了.每次到东北地区的区域赛或者是秦皇岛 ...
- 小学四则运算口算练习app---No.7
今天主要改了设置页面的提示框以及按钮的闪退问题: activity_calculators .class import android.support.v7.app.AppCompatActivity ...
- Linux性能优化实战学习笔记:第六讲1
一.环境准备 1.安装软件包 终端1 机器配置:2 CPU,8GB 内存 预先安装 docker.sysstat.perf等工具 [root@luoahong ~]# docker -v Docker ...
- 写代码注意了,打死都不要用 User 这个单词
阅读本文大概需要 4 分钟. 原文:http://t.cn/Eau2d0h 译文:http://21cto.com/article/2093 当你意识到你在项目开始时做的轻量.简单的设想竟然完全错了时 ...