金伯利jbl娱乐官方手机版金伯利jbl娱乐官方手机版


金百利jbl娱乐备用手机版

.NET Core中的路由约束

背景介绍

上周给大家分享了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"。

本篇源代码

参考文献

Creating Custom Routing Constraint In ASP.NET Core MVCRouting in ASP.NET CoreRoute Constraints in ASP.NET Core

欢迎阅读本文章: 邱新民

金伯利kbl体育官方注册

金百利jbl娱乐备用手机版