0x00 路由模板中的约束
在配置路由模板时,除了以静态字符和变量的形式外,还可以通过配置对变量进行约束。实际如果不嫌麻烦的话在路由到的Action中对变量进行检查也是一种方法,不过对于变量的通用的约束当然是放在路由层面更加合适。而且这样做会简化Action的代码,使Action更加专注于自身业务,符合AOP的思路。这篇文章主要介绍路由模板中的约束。
0x01 在路由模板中使用约束
在路由模板中使用约束是很简单的,如下所示:
1 | {controller=Home}/{action=Index}/{id:int?} |
这个模板就对id进行了约束,约束是通过冒号(:)实现的,冒号后为约束的内容。Int?代表id约束为int?类型,只有id能被转换为int?类型模板匹配才算成功。即使用int.TryParse()方法返回true。
- Home/Index/123匹配成功,id为123
- Home/Index/abc 匹配失败,因为abc无法转换为int?
- Home/Index匹配成功,此时id为null
和配置默认值一样,除了直接在模板中配置外,也可以在MapRoute方法中通过传入参数进行配置:
1 | routes.MapRoute( |
这个模板中id被约束为int类型且最小值为0。同样的也可以以参数的方式配置:
1 | routes.MapRoute( |
可以达到同样的效果,不过直接写到模板更加简洁和直观。
0x02 .NetCore MVC中内建的约束
.NetCore MVC中内建了大量的约束可供使用。其中大多数基于类型的约束都是使用该类型的TryParse()来尝试转换变量提取出来的字符串,返回ture则通过约束,返回false违反约束。
1.约束为int:int,对应的类为IntRouteConstraint
例子:{controller=Home}/{action=Index}/{id:int }
2.约束为float:float,对应的类为FloatRouteConstraint
例子:{controller=Home}/{action=Index}/{id:float }
3.约束为long:long,对应的类为LongRouteConstraint
例子:{controller=Home}/{action=Index}/{id:long}
4.约束为double:double,对应的类为DoubleRouteConstraint
例子:{controller=Home}/{action=Index}/{id:double }
5.约束为decimal:decimal,对应的类为DecimalRouteConstraint
例子:{controller=Home}/{action=Index}/{id:decimal }
6.约束为布尔值:bool,对应的类为BoolRouteConstraint
例子:{controller=Home}/{action=Index}/{id:bool}
7.约束为字母:alpha,对应的类为AlphaRouteConstraint
例子:{controller=Home}/{action=Index}/{id:alpha}
8.约束为时间日期:datetime,对应的类为DateTimeRouteConstraint
例子:{controller=Home}/{action=Index}/{id:datetime}
9.约束为GUID:guid,对应的类为GuidRouteConstraint
例子:{controller=Home}/{action=Index}/{id:bool}
10.约束长度:length(len),对应的类为LengthRouteConstraint(len)
例子:{controller=Home}/{action=Index}/{id:length(5) }
11.约束最小长度:minlength(len),对应的类为MinLengthRouteConstraint(len)
例子:{controller=Home}/{action=Index}/{id:minlength(5)}
12.约束最大长度:maxlength(len),对应的类为MaxLengthRouteConstraint(len)
例子:{controller=Home}/{action=Index}/{id:maxlength(10)}
13.约束长度范围:length(min,max),对应的类为LengthRouteConstraint(min,max)
例子:{controller=Home}/{action=Index}/{id:length(5,10)}
14.约束最小值:min(v),对应的类为MinRouteConstraint(v)
例子:{controller=Home}/{action=Index}/{id:min(0)}
15.约束最大值:max(v),对应的类为MaxRouteConstraint(v)
例子:{controller=Home}/{action=Index}/{id:max(1000)}
16.约束范围:range(min,max),对应的类为RangeRouteConstraint(min,max)
例子:{controller=Home}/{action=Index}/{id:range(0,1000) }
17.约束正则表达式:regex(exp),对应的类为RegexRouteConstraint(exp)
例子:{controller:regex(^My.*)=Home }/{action=Index}/{id?}
0x03 创建自定义约束
除了使用内建的约束外,还可以自定义约束。只要实现IRouteConstraint接口即可。这个接口定义了一个方法:
1 | bool Match( |
这个方法返回ture说明符合约束,返回false说明违反约束。下面我们通过实现这个接口定义一个约束,把id约束为偶数。
1 | public class EvenRouteConstraint : IRouteConstraint |
然后这样配置路由来约束id:
1 | routes.MapRoute( |
这样配置后
- 空Path路由到HomeController的Index,id为空
- Home/Index/12路由到HomeController的Index,id为12,是偶数
- Home/Index/13匹配失败,id为13,不是偶数。
除了使用constraints参数添加自定义路由约束外,也可以把自定义路由约束映射为字符串,用于路由模板中。
1 | public void ConfigureServices(IServiceCollection services) |
这样配置后路由模板写成:
1 | routes.MapRoute( |
可以达到同样的效果。把约束映射为字符串后,还可以方便的在Route特性中使用,例如:
1 | [ ] |
0x04 相关代码
https://github.com/durow/NetCoreStudy/tree/master/src/RouteStudy