在配置路由模板时,除了以静态字符和变量的形式外,还可以通过配置对变量进行约束。实际如果不嫌麻烦的话在路由到的 Action 中对变量进行检查也是一种方法,不过对于变量的通用的约束当然是放在路由层面更加合适。而且这样做会简化 Action 的代码,使 Action 更加专注于自身业务,符合 AOP 的思路。这篇文章主要介绍路由模板中的约束。
在路由模板中使用约束是很简单的,如下所示:
- {
- 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 方法中通过传入参数进行配置:
- routes.MapRoute(name: "default", template: "{controller}/{action}/{id?}", defaults: new {
- controller = "Home",
- action = "Index",
- },
- constraints: new {
- id = new IntRouteConstraint()
- });
效果是一样的。
如果我们要对一个变量使用多个约束,只需要在约束后面继续用冒号加约束即可。例如
- {
- controller = Home
- }
- /{action=Index}/ {
- id: int: min(0)
- }
这个模板中 id 被约束为 int 类型且最小值为 0。同样的也可以以参数的方式配置:
- routes.MapRoute(name: "default", template: "{controller}/{action}/{id?}", defaults: new {
- controller = "Home",
- action = "Index",
- },
- constraints: new {
- id = new CompositeRouteConstraint(new IRouteConstraint[] {
- new IntRouteConstraint(),
- new MinRouteConstraint(0)
- })
- });
可以达到同样的效果,不过直接写到模板更加简洁和直观。
.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?}"
除了使用内建的约束外,还可以自定义约束。只要实现 IRouteConstraint 接口即可。这个接口定义了一个方法:
- bool Match(HttpContext httpContext, //Http上下文信息
- IRouter route, //当前正在测试的模板信息
- string routeKey, //当前正在测试约束的变量名称
- RouteValueDictionary values, //模板中变量提取出的值
- RouteDirection routeDirection) //路由方向,枚举,值包括IncominRequestg和UrlGeneration
这个方法返回 ture 说明符合约束,返回 false 说明违反约束。下面我们通过实现这个接口定义一个约束,把 id 约束为偶数。
- public class EvenRouteConstraint: IRouteConstraint {
- public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) {
- int id;
- if (!int.TryParse(values[routeKey].ToString(), out id)) return false;
- return id % 2 == 0;
- }
- }
然后这样配置路由来约束 id:
- routes.MapRoute(name: "default", template: "{controller}/{action}/{id?}", defaults: new {
- controller = "Home",
- action = "Index",
- },
- constraints: new {
- id = new EvenRouteConstraint()
- });
这样配置后
空 Path 路由到 HomeController 的 Index,id 为空
Home/Index/12 路由到 HomeController 的 Index,id 为 12,是偶数
Home/Index/13 匹配失败,id 为 13,不是偶数。
除了使用 constraints 参数添加自定义路由约束外,也可以把自定义路由约束映射为字符串,用于路由模板中。
- public void ConfigureServices(IServiceCollection services) {
- services.Configure(options = >{
- options.ConstraintMap.Add("even", typeof(EvenRouteConstraint));
- });
- // Add framework services.
- services.AddMvc();
- }
这样配置后路由模板写成:
- routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id:even?}");
- });
可以达到同样的效果。把约束映射为字符串后,还可以方便的在 Route 特性中使用,例如:
- [Route("durow/Test/[action]/{id:even?}")]
https://github.com/durow/NetCoreStudy/tree/master/src/RouteStudy
来源: http://www.cnblogs.com/durow/p/6012788.html