背景介绍

上周给大家分享了Nancy in .NET Core学习笔记 - 路由之后, 就一直在考虑.NET Core能否实现和Nancy中一样的路由约束, 最近查阅了一下MSDN及一些国外博客, 发现.NET Core中已经实现了相同的功能,所以这里给大家分享一下。

路由约束

路由约束是路由中的一种设置,可以帮助我们限制Url中的参数类型,只有当参数符合约束条件的时候,action才会被激活并触发。

比如我们现在有以下2个Url

[GET] /api/posts/{id}

[GET] /api/posts/{name}

我们希望当Posts后面的参数是int类型的时候触发第一个Url所指向action, 参数是string类型的时候触发第二个Url所指向的action。

在这种场景下,我们就需要使用路由约束。

如何添加路由约束

在.NET Core中有2种添加路由约束的方法。

  • 行内约束(Inline Constraint)
  • 使用MapRoute方法带Constraint参数的重载

当路由引擎发现当前的请求Url符合某个路由设置之后,就会去触发当前路由设置中的所有路由约束,当所有的约束都返回true, 这个路由对应的action就会被激活。

行内约束(Inline Constraint)

所谓的行内约束,即在路由Url模板中直接定义。定义的方式是在参数后面加冒号,并制定约束类型。

例:

"/api/posts/{id:int}"

所以该方式既可以在MapRoute方法中使用,也可以在路由属性中使用。

在MapRoute方法中使用

routes.MapRoute("default", "{controller=Home}/{action=Index}/{id:int}");

在路由属性中使用

[Route("Home/Index/{id:int}")]
public string Index(int id)
{
return "I got " + id.ToString();
}

使用MapRoute方法带Constraint参数的重载

除了行内约束,我们还可以在Startup.cs的中通过app.UseMvc()方法来添加约束。

例:

using Microsoft.AspNetCore.Routing.Constraints;

app.UseMvc(routes =>
{
routes.MapRoute("default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index" },
new { id = new IntRouteConstraint() });
});

.NET Core内置的路由约束

.NET Core已经提供了很多基础的路由约束,总体上分为3种类型。

  • 检查数据类型的约束
  • 检查数据的值/长度/范围的约束
  • 正则表达式约束

检查数据类型的约束

约束 行内 Constraint类 说明
int {id:int} IntRouteConstraint 只允许int32整数
alpha {id:alpha} AlphaRouteConstraint 只能包含大小写字母
bool {id:bool} BoolRouteConstraint 只允许布尔类型
datetime {id:datetime} DateTimeRouteConstraint 只允许日期格式
decimal {id:decimal} DecimalRouteConstraint 只允许decimal类型
double {id:double} DoubleRouteConstraint 只允许double类型
float {id:float} FloatRouteConstraint 只允许float类型
guid {id:guid} GuidRouteConstraint 只允许guid类型

检查数据的值/长度/范围的约束

约束 行内 Constraint类 说明
length(length) {id:length(12)} LengthRouteConstraint 字符串长度限制
maxlength(value) {id:maxlength(8)} MaxLengthRouteConstraint 字符串最大长度限制
minlength(value) {id:minlength(4)} MinLengthRouteConstraint 字符串最小长度限制
range(min,max) {id:range(18,120)} RangeRouteConstraint 数值范围限制
min(value) {id:min(18)} MinRouteConstraint 最小数值限制
max(value) {id:max(120)} MaxRouteConstraint 最大数值限制

正则表达式约束

约束 行内 Constraint类 说明
regex(expression) {ssn:regex(^\d{{3}}-\d{{2}}-\d{{4}}$)}/ RegexRouteConstraint 正则表达式约束

自定义路由约束

和Nancy一样,.NET Core也支持自定义路由约束,我们可以通过实现IRouteConstraint接口的Match方法来自定义路由约束。

我们举一个和之前Nancy in .NET Core学习笔记 - 路由中的类似的例子。

当前我们有一个PostController类,代码如下:

    [ApiController]
public class PostController : ControllerBase
{
[HttpGet]
[Route("~/api/posts/{id:int}")]
public IActionResult GetPostById(int id)
{
return Content("Coming from GetPostById");
} [HttpGet]
[Route("~/api/posts/{name:alpha}")]
public IActionResult GetPostByName(string name)
{
return Content("Coming from GetPostByName");
}
}

这时候我们添加新的action方法GetPostByEmail, 并追加一个email约束,方法如下:

    [HttpGet]
[Route("~/api/posts/{email:email}")]
public IActionResult GetPostByEmail(string email)
{
return Content("Coming from GetPostByEmail");
}

我们希望当posts后面的参数是email格式的时候,显示"Coming from GetPostByEmail"。

这里我们首先添加一个EmailConstraint类,并实现IRouteConstraint接口的Match方法

    public class EmailConstraint : IRouteConstraint
{
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
if (httpContext == null)
throw new ArgumentNullException(nameof(httpContext)); if (route == null)
throw new ArgumentNullException(nameof(route)); if (routeKey == null)
throw new ArgumentNullException(nameof(routeKey)); if (values == null)
throw new ArgumentNullException(nameof(values)); object routeValue; if (values.TryGetValue(routeKey, out routeValue))
{
var parameterValueString = Convert.ToString(routeValue, CultureInfo.InvariantCulture); return parameterValueString.Contains("@");
} return false;
}
}

其中values.TryGetValue(routeKey, out routeValue)是尝试从路由参数列表中,取出当前参数的值, 如果当前值中包含@, 我们就简单的认为这个Email约束通过, 并返回true。


上述代码完成之后,我们打开Startup.cs文件, 在ConfigureServices方法中, 我们将这个自定义的路由约束添加到约束列表中,并指定当前的约束名称是email。

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.Configure<RouteOptions>(routeOptions =>
{
routeOptions.ConstraintMap.Add("email", typeof(EmailConstraint));
});
}

最后我们看一下效果, 页面中正确显示除了"Coming from GetPostByEmail"。

本篇源代码

参考文献

.NET Core中的路由约束的更多相关文章

  1. ASP.NET Core中自定义路由约束

    路由约束 ASP.NET Core中,通过定义路由模板,可以在Url上传递变量,同时可以针对变量提供默认值.可选和约束. 约束的使用方法是在属性路由上添加指定的约束名,用法如下: // 单个使用 [R ...

  2. 在ASP.NET Core中构建路由的5种方法

    原文链接 :https://stormpath.com/blog/routing-in-asp-net-core 在ASP.NET Core中构建路由的5种方法 原文链接 :https://storm ...

  3. C#调用接口注意要点 socket,模拟服务器、客户端通信 在ASP.NET Core中构建路由的5种方法

    C#调用接口注意要点   在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用, 所以首先需要通过调用登录接口来保存c ...

  4. webapi中的路由约束

    Route Constraints Route constraints let you restrict how the parameters in the route template are ma ...

  5. asp.net core 中的路由

  6. ASP.NET Core的路由[5]:内联路由约束的检验

    当某个请求能够被成功路由的前提是它满足某个Route对象设置的路由规则,具体来说,当前请求的URL不仅需要满足路由模板体现的路径模式,请求还需要满足Route对象的所有约束.路由系统采用IRouteC ...

  7. ASP.NET Core 中文文档 第四章 MVC(4.2)控制器操作的路由

    原文:Routing to Controller Actions 作者:Ryan Nowak.Rick Anderson 翻译:娄宇(Lyrics) 校对:何镇汐.姚阿勇(Dr.Yao) ASP.NE ...

  8. 使用.NET Core在RESTful API中进行路由操作

    介绍 当列出REST API的最佳实践时,Routing(路由)总是使它位于堆栈的顶部.今天,在这篇文章中,我们将使用特定于.NET Core的REST(web)API来处理路由概念. 对于新手API ...

  9. (9)ASP.NET Core 中的MVC路由二

    1.URL生成 MVC应用程序可以使用路由的URL生成功能,生成指向操作(Action)的URL链接. IUrlHelper 接口用于生成URL,是MVC与路由之间的基础部分.在控制器.视图和视图组件 ...

随机推荐

  1. 分布式缓存技术之Redis_01数据结构分析

    目录 官网 1. 分布式缓存技术的应用 2. Redis的安装指引 官网  redis.io  redisDoc 1. 分布式缓存技术的应用 2. Redis的安装指引 官网下载安装包 redis-5 ...

  2. Linux磁盘和文件系统管理

    1.检测并确认新硬盘 挂载好新的硬盘设备并启动主机后,Linux系统会自动检测并加载该硬盘,无须额外安装驱动.执行“fdisk -l”命令即可查看,确认新增硬盘的设备名称和位置.作用:列出当前系统中所 ...

  3. jdk1.8安装

    jdk1.8:链接: https://pan.baidu.com/s/1Orv7Rjz0jkprcdoRSFWiPw 提取码: rn73 设置jdk和jre文件位置 配置环境变量: 系统变量中jdk ...

  4. jQuery 动态绑定插件livequery的用法

  5. Oracle DBLINK的相关知识整理

    一.DBLINK(Database Link)概念 dblink,顾名思义就是数据库的链接.当我们要跨本地数据库访问另一个数据库中的表的数据时,在本地数据库中就必须要创建远程数据库的dblink,通过 ...

  6. spring-cloud-Zuul学习(四)【中级】--自定义zuul Filter详解【重新定义spring cloud实践】

      实现自定义zuul Filter 方法很简单,只要继承ZuulFilter跟加入到spring IOC容器即可,zuulFilter是一个抽象类,里面包含以下方法需要我们实现: String fi ...

  7. Flask的上下文源码剖析

    先写一段Flask程序 from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return ...

  8. OJ001

    #include<stdio.h> int main(){ int a,b; while (scanf("%d%d",&a,&b)!=EOF){ pri ...

  9. 解决用友U8删除用户时提示“用户已启用”不能删除的问题

    USE UFSystem go DECLARE @cUser_Id NVARCHAR(20) SET @cUser_Id='用户的登录名' DELETE l FROM dbo.UA_TaskLog l ...

  10. Lesson 26 The best art critics

    Text I am an art student and I paint a lot of pictures. Manay people pretend that they understand mo ...