ASP.NET Core 入门教程 3、ASP.NET Core MVC路由入门
一、前言
1、本文主要内容
- ASP.NET Core MVC路由工作原理概述
- ASP.NET Core MVC带路径参数的路由示例
- ASP.NET Core MVC固定前/后缀的路由示例
- ASP.NET Core MVC正则表达式匹配路由示例
- ASP.NET Core MVC路由约束与自定义路由约束
- ASP.NET Core MVC RouteAttribute绑定式路由使用介绍
2、本教程环境信息
| 软件/环境 | 说明 |
|---|---|
| 操作系统 | Windows 10 |
| SDK | 2.1.401 |
| ASP.NET Core | 2.1.3 |
| IDE | Visual Studio Code 1.27 |
| 浏览器 | Chrome 69 |
本篇代码基于上一篇进行调整:https://github.com/ken-io/asp.net-core-tutorial/tree/master/chapter-02
3、前置知识
你可能需要的前置知识
- MVC框架/模式介绍
https://baike.baidu.com/item/mvc
- 正则表达式
http://www.runoob.com/regexp/regexp-tutorial.html
二、ASP.NET Core MVC 路由简介
1、ASP.NET Core MVC路由工作原理概述
ASP.NET Core MVC路由的作用就是将应用接收到请求转发到对应的控制器去处理。
应用启动的时候会将路由中间件(RouterMiddleware)加入到请求处理管道中,并将我们配置好的路由加载到路由集合(RouteCollection)中。当应用接收到请求时,会在路由管道(路由中间件)中执行路由匹配,并将请求交给对应的控制器去处理。
另外,需要特别注意的是,路由的匹配顺序是按照我们定义的顺序从上之下匹配的,遵循是的先配置先生效的原则。
2、路由配置参数说明
| 参数名 | 说明 |
|---|---|
| name | 路由名称,不可重复 |
| template | 路由模板,可在模板中以{name}格式定义路由参数 |
| defaults | 配置路由参数默认值 |
| constraints | 路由约束 |
在路由配置中,MVC框架内置了两个参数,controller,action。
路由匹配通过后,需要根据这两个参数将当前请求交由对应的Controller+Action去处理。所以,这两个参数缺少任何一个,都会导致路由无法正常工作。
通常我们有两个选择:
- 在template中指定{controller},{action}参数
- 在默认值中为controller、action指定默认值
三、ASP.NET Core MVC 路由示例
1、准备工作
为了方便我们进行测试,我们先准备好承接路由的Controller&Action
- 创建TutorialController
在Controllers文件夹下新增控制器TutorialController.cs并继承于Controller
using System;
using Microsoft.AspNetCore.Mvc;
namespace Ken.Tutorial.Web.Controllers
{
public class TutorialController : Controller
{
}
}
- 增加Action:Index
public IActionResult Index()
{
return Content("ASP.NET Core Tutorial by ken from ken.io");
}
- 增加Action:Welcome
public IActionResult Welcome(string name, int age)
{
return Content($"Welcome {name}(age:{age}) !");
}
2、带路径参数的路由
路由配置:
routes.MapRoute(
name: "TutorialPathValueRoute",
template: "{controller}/{action}/{name}/{age}"
);
此路由适配URL:
- /tutorial/welcome/ken/20
不适配URL:
- /tutorial/welcome/ken
如果我们希望不在路径中设置age,也可以被路由到,那么可以将age指定为可选参数,将模板中的{age}修改为{age?}即可
routes.MapRoute(
name: "TutorialPathValueRoute",
template: "{controller}/{action}/{name}/{age?}"
);
此路由适配URL:
- /tutorial/welcome/ken/20
- /tutorial/welcome/ken
- /tutorial/welcome/ken?age=20
3、固定前后缀的路由
固定前缀路由配置:
routes.MapRoute(
name: "TutorialPrefixRoute",
template: "jiaocheng/{action}",
defaults: new { controller = "Tutorial" }
);
此路由适配URL:
- /jiaocheng/index
- /jiaocheng/welcome
由于路径参数中不包含controller参数,所以需要在默认值中指定。
固定后缀路由配置
routes.MapRoute(
name: "TutorialSuffixRoute",
template: "{controller}/{action}.html"
);
此路由适配URL:
- /tutorial/index.html
- /tutorial/welcome.html
- /home/index.html
- /home/time.html
固定后缀的路由适用于伪静态等诉求
固定前后缀可以根据自己的需求结合起来使用。
当然,你也可以在路由模板中间设定固定值。
四、ASP.NET Core MVC 路由约束
1、路由约束介绍
路由约束主要是用于约束路由参数,在URL格式满足路有模板要求之后,进行参数检查。如果参数不满足路由约束,那么依然会返回未匹配该路由。最常用的可能就是参数类型校验、参数长度校验、以及通过正则满足的复杂校验。
在开始之前需要在Startup.cs中引用相关命名空间
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Constraints;
2、参数长度约束
路由配置:约束name长度不能>5
routes.MapRoute(
name: "TutorialLengthRoute",
template: "hello/{name}/{age?}",
defaults: new { controller = "Tutorial", action = "Welcome", name = "ken" },
constraints: new { name = new MaxLengthRouteConstraint(5) }
);
此路由适配
- /hello
- /hello/ken
- /hello/ken/1000
次路由不适配
- /hello/kenaaaa
我们也可以直接在模板中配置路由约束:
routes.MapRoute(
name: "TutorialLengthRoute2",
template: "hello2/{name:maxlength(5)}/{age?}",
defaults: new { controller = "Tutorial", action = "Welcome", name = "ken" }
);
3、参数范围约束
路由配置:约束 1<=age<=150
routes.MapRoute(
name: "TutorialLengthRoute",
template: "hello/{name}/{age?}",
defaults: new { controller = "Tutorial", action = "Welcome", name = "ken" },
constraints: new { age = new CompositeRouteConstraint(new IRouteConstraint[] {
new IntRouteConstraint(),
new MinRouteConstraint(1),
new MaxRouteConstraint(150) }) }
);
此路由适配:
- /hello/ken/1
- /hello/ken/150
此路由不适配
- /hello/ken/1000
我们也可以直接在模板中配置路由约束:
routes.MapRoute(
name: "TutorialLengthRoute2",
template: "hello2/{name}/{age:range(1,150)?}",
defaults: new { controller = "Tutorial", action = "Welcome", name = "ken" }
);
4、带有正则表达式约束的路由
路由配置:
routes.MapRoute(
name: "TutorialRegexRoute",
template: "welcome/{name}",
defaults: new { controller = "Tutorial", Action = "Welcome" },
constraints: new { name = @"k[a-z]*" }
);
此路由适配:
- /welcome/k
- /welcome/ken
- /welcome/kevin
此路由不适配
- /welcome/k1
- /welcome/keN
- /welcome/tom
这里我们用正则表达式约束了参数name,必须通过正则k[a-z]*匹配通过,即:以小写字母k开头,且后续可跟0到多个小写字母
我们也可以直接在模板中配置路由约束:
routes.MapRoute(
name: "TutorialRegexRoute2",
template: "welcome2/{name:regex(@"k[a-z]*")}",
defaults: new { controller = "Tutorial", Action = "Welcome" }
);
5、自定义路由约束
1、创建自定义约束
在项目根目录创建目录Common,并在目录创建类:NameRouteConstraint.cs,然后实现接口:IRouteConstraint
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
namespace Ken.Tutorial.Web.Common
{
public class NameRouteConstraint : IRouteConstraint
{
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
string name = values["name"]?.ToString();
if (name == null) return true;
if (name.Length > 5 && name.Contains(",")) return false;
return true;
}
}
}
这里我们约束当name长度>5时,name中不能包含,
2、路由配置
引入命名空间
using Ken.Tutorial.Web.Common;
在ConfigureServices引入路由约束
public void ConfigureServices(IServiceCollection services)
{
//引入MVC模块
services.AddMvc();
//引入自定义路由约束
services.Configure<RouteOptions>(options =>
{
options.ConstraintMap.Add("name", typeof(NameRouteConstraint));
});
}
配置路由
routes.MapRoute(
name: "TutorialDiyConstraintRoute",
template: "diy/{name}",
defaults: new { controller = "Tutorial", action = "Welcome" },
constraints: new { name = new NameRouteConstraint() }
);
此路由适配:
- /diy/ken
- /diy/ken,
- /diy/kenny
此路由不适配
- /diy/kenny,
当然,按照惯例,依然可以在模板中配置路由约束
routes.MapRoute(
name: "TutorialDiyConstraintRoute2",
template: "diy2/{name:name}",
defaults: new { controller = "Tutorial", action = "Welcome" }
);
五、ASP.NET Core MVC 绑定式路由配置
1、路由配置风格
- 集中式配置
前面章节提到的路由配置都是在Startup类中进行的集中式路由配置,集中配置的路由,除了template中没有配置{controller}参数,默认都是对所有控制器(Controller)生效的。这种集中配置的方式一般我们只要配置一个默认路由,其他情况我们只需要不满足默认模板的情况下进行配置即可。尤其是对URL没有友好度要求的应用,例如:后台管理系统
- 分散式配置/绑定式配置
对于集中式路由配置的方式,如果某个Controller/Action配置了特殊路由,对于代码阅读就会不太友好。不过没关系,ASP.NET Core MVC也提供了RouteAttribute可以让我们在Controller或者Action上直接指定路由模板。
不过要强调的是,一个控制器只能选择其中一种路由配置,如果控制器标记了RouteAttribute进行路由配置,那么集中式配置的路由将不对其生效。
2、绑定式路由配置
在项目Controllers目中新建TestController.cs继承与Controller
并配置Action与路由
using System;
using Microsoft.AspNetCore.Mvc;
namespace Ken.Tutorial.Web.Controllers
{
[Route("/test")]
public class TestController : Controller
{
[Route("")]
[Route("/test/home")]
public IActionResult Index()
{
return Content("ASP.NET Core RouteAttribute test by ken from ken.io");
}
[Route("servertime")]
[Route("/t/t")]
public IActionResult Time(){
return Content($"ServerTime:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} - ken.io");
}
}
}
| 配置项 | 说明 |
|---|---|
| [Route("/test")] | 表示该Controller访问路由前缀为/test,必须以/开头 |
| [Route("")] | 表示以Controller的路由配置为前缀访问该Action;可以通过/test路由到该Action |
| [Route("/test/home")] | 表示忽略Controller的路由配置;可以通过/test/home路由到该Action |
| [Route("servertime")] | 表示以Controller的路由配置为前缀访问该Action;可以通过/test/servertime路由到该Action |
| [Route("/t/t")] | 表示忽略Controller的路由配置;可以通过/t/t路由到该Action |
RouteAttribute中配置的参数,就相当于我们集中式配置中的路由模板(template),最终框架还是帮我们初始化成路由规则,以[Route("/test/home")]为例,相当于生成了以下路由配置:
routes.MapRoute(
name: "Default",
template: "test/home",
defaults: new { controller = "Test", action = "Index" }
);
当然,我们也可以在[Route]配置中使用模板参数,而且依然可以在模板中使用约束,自定义约束也没问题。
[Route("welcome/{name:name}")]
public IActionResult Welcome(string name){
return Content($"Welcome {name} !");
}
最大的区别就是不能定义默认值了,可能也不需要了,你说是吧。_
六、备注
1、附录
- 本文代码示例
https://github.com/ken-io/asp.net-core-tutorial/tree/master/chapter-03
- 本文参考
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/routing?view=aspnetcore-2.1
本文首发于我的独立博客: https://ken.io/note/asp.net-core-tutorial-mvc-route
ASP.NET Core 入门教程 3、ASP.NET Core MVC路由入门的更多相关文章
- ASP.NET Core 基础教程总结 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 基础教程总结 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 基础教程总结 ASP.NET Core 基础教程总算是有了个简单 ...
- ASP.NET Core 基础教程-约定 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 基础教程-约定 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 基础教程-约定 因为 ASP.NET Core 是可以跨平台的 ...
- Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导
Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导 Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导 必要的message类实现 从下面开始是在veins/src/vei ...
- 1,[VS入门教程] 使用Visual Studio写c语言 入门与技巧精品文~~~~下载安装篇
Microsoft Visual Studio是微软(俗称巨硬)公司出品的强大IDE(Integrated Development Environment 集成开发环境),功能强大齐全,界面舒服之类的 ...
- ASP.NET Core 入门笔记4,ASP.NET Core MVC路由入门
敲了一部分,懒得全部敲完,直接复制大佬的博客了,如有侵权,请通知我尽快删除修改 摘抄自https://www.cnblogs.com/ken-io/p/aspnet-core-tutorial-mvc ...
- Java - Struts框架教程 Hibernate框架教程 Spring框架入门教程(新版) sping mvc spring boot spring cloud Mybatis
https://www.zhihu.com/question/21142149 http://how2j.cn/k/hibernate/hibernate-tutorial/31.html?tid=6 ...
- 【CC2530入门教程-01】CC2530微控制器开发入门基础
[引言] 本系列教程就有关CC2530单片机应用入门基础的实训案例进行分析,主要包括以下6部分的内容:[1]CC2530微控制器开发入门基础.[2]通用I/O端口的输入和输出.[3]外部中断初步应用. ...
- ASP.NET请求过程-从源码角度研究MVC路由、Handler、控制器
路由常用对象 RouteBase 用作表示 ASP.NET 路由的所有类的基类. 就是路由的一个基础抽象类. // // 摘要: // 用作表示 ASP.NET 路由的所有类的基类. [ ...
- RabbitMQ官方中文入门教程(PHP版) 第四部分:路由(Routing)
路由(Routing) 在前面的教程中,我们实现了一个简单的日志系统.可以把日志消息广播给多个接收者. 本篇教程中我们打算新增一个功能——使得它能够只订阅消息的一个字集.例如,我们只需要把严重的错误日 ...
随机推荐
- [Swift]LeetCode188. 买卖股票的最佳时机 IV | Best Time to Buy and Sell Stock IV
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- Npoi简单读写Excel
什么是NPOI ? 简而言之,NPOI就是可以在没有Office的情况下对Word或Excel文档进行读写等操作. 使用方式 : 1.准备NPOI的dll文件 下载链接:https://npoi.co ...
- 交叉编译 tcpdump
目录 1. 下载 tcpdump 2. 交叉编译 3. 相关说明 1. 下载 tcpdump 官网:http://www.tcpdump.org/ 2. 交叉编译 交叉编译libpcap: $ wge ...
- 使用C# (.NET Core) 实现抽象工厂设计模式 (Abstract Pattern)
本文的概念性内容来自深入浅出设计模式一书. 上一篇文章讲了简单工厂和工厂方法设计模式 http://www.cnblogs.com/cgzl/p/8760250.html, 使用的是披萨店的例子. 文 ...
- slf4j 和 log4j的关系及合用Maven配置
最近因为项目实在是太忙,都没有时间学习.有时候会很矛盾,一方面是全心全意的想去快速做完项目,一方面又想学习点新东西.这样导致这两三个月都没有去学习一些新的东西,这周我开始创建自己的maven项目,因为 ...
- JSON 序列化的时候忽略无效的属性值
例如我拥有以下代码. public class NewObject { public int? TestValue { get; set; } public int? Age { get; set; ...
- Java接口的实例应用:致敬我的偶像——何塞·穆里尼奥
文/沉默王二 曹操在<短歌行>中为杜康酒打过一个价值一亿个亿的广告——“何以解忧,唯有杜康”,我替曹操感到惋惜的是他本人并不会收到这笔不菲的代言费.想一想,要是三国时期的明星人物们有这个代 ...
- 认识浏览器请求头User-Agent
一.定义 User Agent中文名为用户代理,是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA. 它是一个特殊字符串头,是一种向访问网站提供你所使用的浏览器类型及版本.操 ...
- Python实战171201筛选数据
Python应用:网络编程,系统网络运维,3D游戏开发,图形界面开发,科学与数字计算,web后端. 对着慕课的练习,果然慕课的实战也是差距很大-------centos7 -Python3.6.3 筛 ...
- .NetCore2.1 WebAPI 根据swagger.json自动生成客户端代码
前言 上一篇博客中我们可以得知通过Swagger插件可以很方便的提供给接口开发者在线调试,但是实际上Swagger附带的功能还有很多, 比如使用NSwag生成客户端调用代码,进一步解放接口开发者. N ...