p { margin-bottom: 0.25cm; direction: ltr; color: #000000; line-height: 120%; orphans: 2; widows: 2 }
p.western { font-family: "Liberation Serif", "Times New Roman", serif; font-size: 12pt }
p.cjk { font-family: "Noto Sans CJK SC Regular"; font-size: 12pt }
p.ctl { font-family: "Noto Sans CJK SC Regular"; font-size: 12pt }
a:link { }

.NetCore MVC中的路由(2)在路由中使用约束

0x00
路由模板中的约束

在配置路由模板时,除了以静态字符和变量的形式外,还可以通过配置对变量进行约束。实际如果不嫌麻烦的话在路由到的Action中对变量进行检查也是一种方法,不过对于变量的通用的约束当然是放在路由层面更加合适。而且这样做会简化Action的代码,使Action更加专注于自身业务,符合AOP的思路。这篇文章主要介绍路由模板中的约束。

0x01
在路由模板中使用约束

在路由模板中使用约束是很简单的,如下所示:

{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:)}

这个模板中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(),
                )
            })
});

可以达到同样的效果,不过直接写到模板更加简洁和直观。

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接口即可。这个接口定义了一个方法:

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;

         == ;
    }
}

然后这样配置路由来约束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<RouteOptions>(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?}")]

0x04 相关代码

https://github.com/durow/NetCoreStudy/tree/master/src/RouteStudy

.NetCore MVC中的路由(2)在路由中使用约束的更多相关文章

  1. .NetCore MVC中的路由(1)路由配置基础

    .NetCore MVC中的路由(1)路由配置基础 0x00 路由在MVC中起到的作用 前段时间一直忙于别的事情,终于搞定了继续学习.NetCore.这次学习的主题是MVC中的路由.路由是所有MVC框 ...

  2. MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)

    前言:上篇介绍了下自己的MVC框架前两个版本,经过两天的整理,版本三基本已经完成,今天还是发出来供大家参考和学习.虽然微软的Routing功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...

  3. MVC路由探寻,涉及路由的惯例、自定义片段变量、约束、生成链接和URL等

    引子 在了解MVC路由之前,必须了解的概念是"片段".片段是指除主机名和查询字符串以外的.以"/"分隔的各个部分.比如,在http://site.com/Hom ...

  4. ASP.NET MVC简单编程之(二)经典路由篇

    话题:请求从路由开始 在实际的ASP.NET MVC开发中,URL访问规则----路由的定义是非常重要的.因为任何一个请求都离不开路由.理解它,我们将能理解MVC处理请求的整个过程,灵活地定义系统各种 ...

  5. ASP.NET MVC学习(一)之路由篇Route

    什么是路由 通过[路由]配置,路由可以规定URL的特殊格式,使其达到特殊效果. 在ASP.NET MVC框架中,通过路由配置URL,使用户的URL请求可以映射到Controller下的action方法 ...

  6. ASP.NET MVC , ASP.NET Web API 的路由系统与 ASP.NET 的路由系统是怎么衔接的?

      ASP.NET MVC 的路由实际上是建立在 ASP.NET 的路由系统之上的. MVC 路由注册通常是这样的: RouteTable 是一个全局路由表, 它的 Routes 静态属性是一个 Ro ...

  7. MVC进阶篇(二)—路由机制

    前言 这个东西好像,一般也不经常动,都用默认的即可.由于MVC模式在framework里面的解析机制,区别与webform模式,是采用解析路由机制的url.从来实例化视图列对象,然后对该action进 ...

  8. vue中如何不通过路由直接获取url中的参数

    前言:为什么要不通过路由直接获取url中的参数? vue中使用路由的方式设置url参数,但是这种方式必须要在路径中附带参数,而且这个参数是需要在vue的路由中提前设置好的. 相对来说,在某些情况下直接 ...

  9. &lt;原&gt;ASP.NET 学习笔记之HTML helper中参数何时会是路由参数,何时又会是query string?

    HTML helper中参数何时会是路由参数,何时又会是query string?   @Html.ActionLink("Edit", "Edit", new ...

随机推荐

  1. is和as

    一.明确两个基本概念 隐式转换: a.对于值类型,低精度=>高精度.eg:int=>long b.对于引用类型,子类向祖宗类转换过程.eg:对象=>Object 显式转换:显示转换是 ...

  2. 总结Objective-c常用算法

          今天是星期天,想睡到10点起床,结果认为自己太奢侈了,不能这么做,于是把闹钟设置成了6:30:结果终于9:36醒了,起床,无缘无故迟了,好吧,就算太累了吧,周天就原谅自己一回.终于到了中午 ...

  3. js去掉字符串前后空格的五种方法

    转载 :http://www.2cto.com/kf/201204/125943.html 第一种:循环检查替换[javascript]//供使用者调用  function trim(s){  ret ...

  4. POJ2187 Beauty Contest

    Description Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, ea ...

  5. Linux常用命令_(文件权限)

    Linux权限管理: 二.权限管理1.3种基本权限在Linux中,将使用系统资源的人员分为4类:超级用户.文件或目录的属主.属主的同组人和其他人员.超级用户拥有对Linux系统一切操作权限,对 于其他 ...

  6. JavaScript中的Get和Set访问器

    今天要和大家分享的是JavaScript中的Get和Set访问器,和C#中的访问器非常相似. 标准的Get和Set访问器的实现   function Field(val){       this.va ...

  7. C# DataGridView的列对象属性探讨 (未完待续)

    比较难的几个属性的释义[1]:

  8. GIS Tools for Hadoop 详细介绍

    2013年Esri美国在开发者大会上演示了GIS数据结合Hadoop分析的一个示例,这个示例赢得了听众的阵阵掌声,我们也许对GIS不是很陌生,但是对Hadoop却不是很清楚,其实Esri是用Java开 ...

  9. iOS设置截图背景图片透明

    /** 设置图片背景为透明 */- (UIImage *)imageToTransparent { // 分配内存 const int imageWidth = self.size.width; co ...

  10. 精度 Precision

    柏拉图认为,尽管世间万物是不完美的,但存在一种永恒不变的形式,这个形式是完美的,而生命的意义就是让这个世界尽可能的接近这个完美的形式. 怎么理解这句话,和我们今天讲的精度有什么关系.我们先举一个例子, ...