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

.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: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)
            })
});

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

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;

        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<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

时间: 2024-08-04 19:06:41

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

在 MVC Controller 中,不依靠定制路由,随心所欲地拦截请求和处理请求,想怎么输入输出都

Asp.net 中的 MVC,其主要面向 "text" 类型的 Content-Type 来处理 HTTP 请求,除了文件传输之外,就连 json.xml 也都是文本类型. 因此,对于 text 类型的输入输出,MVC 自然处理得很好.可有时候,这并不能令我们满意. 当我们要传输二进制 byte[] 数组.序列化结构数据.以及任何特殊请求的处理时,该怎么办呢?难道非要将它们以 base64 编码,抑或是为特殊请求定制一个路由,譬如转到 IHttpHandler/IRouteHandle

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

引子 在了解MVC路由之前,必须了解的概念是"片段".片段是指除主机名和查询字符串以外的.以"/"分隔的各个部分.比如,在http://site.com/Home/Index中,包含2个片段,第一个片段是Home,第二个片段是Index. URL匹配的特点:● 保守的:URL中的片段数量必须和路由规则中的片段数量一致(路由规则没有设置默认值的前提下)● 宽松的:在满足片段数要求的前提下,URL中的片段内容是宽松的 本篇涉及的方面包括:1.路由惯例2.自定义片段变量3

可编辑路由&mdash;Asp.NET MVC项目编译后,修改路由配置可动态加载

Asp.NET MVC 应用程序一旦完成部署到线上后,就不能够修改路由配置,只有重新编译应用程序,重新部署到程序集才能够完成,最近在学习过程中看到了一篇博客关于如何更改路由选项后,能够直接运行到已部署的应用程序中. 首先看看我在程序中,解决方案的结构选项,方便学习,,Route文件夹中放的是这次需要的类文件和接口,在控制器中我定义了一个HomeController 在里面定义了Index和Modify两个方法,也在Views文件夹中定义了相应的视图用于测试使用. 1,定义一个IRouteRegi

asp.netCore3.0 中使用app.UseMvc() 配置路由

一.新配置路由策略  在 Asp.Net Core 3.0中默认不再支持app.UserMvc() 方式配置路由 系统. 而是使用新的模式,点击查看asp.netCore3.0区域和路由配置变化 默认使用的话 会抛出异常: InvalidOperationException: Endpoint Routing does not support 'IApplicationBuilder.UseMvc(...)'. To use 'IApplicationBuilder.UseMvc' set 'M

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

前言:为什么要不通过路由直接获取url中的参数? vue中使用路由的方式设置url参数,但是这种方式必须要在路径中附带参数,而且这个参数是需要在vue的路由中提前设置好的. 相对来说,在某些情况下直接在url后面拼接?mid=100的方式传递参数更灵活,你不需要设置路由,只需要在url后拼接参数即可,但是这种方式就需要通过javascript获取并提取url中的参数,通过传统的方式直接在页面中获取是行不通的了,因为vue中是无法通过location.search()来获取url问号之后的内容的.

MVC系列学习(十四)-路由规则及路由调试工具

1.本次学习的代码,比较简单,就是在路由配置文件中,添加一个路由信息:同时添加一个相应的控制器及视图 控制器中代码如下 即有两条路由匹配规则,一个Kim控制器,该控制器下有个Index的方法,和一个对应Index视图 2.开始配置RouteDebugger 2.1下载程序集 RouteDebugger-2.1.3.0下载地址 2.2添加引用,并配置RouteDebugger 在网站根目录下的web.config文件中,在<appSetting></appSetting>节点中,添加

在GNS3 1.3.10中进行简单的静态路由配置

在GNS3 1.3.10中进行简单的静态路由配置 简介: GNS3是一款具有图形化界面可以运行在多平台(包括Windows, Linux, and MacOS等)的网络虚拟软件.Cisco网络设备管理员或是想要通过CCNA,CCNP,CCIE等Cisco认证考试的相关人士可以通过它来完成相关的实验模拟操作.同时它也可以用于虚拟体验Cisco网际操作系统IOS或者是检验将要在真实的路由器上部署实施的相关配置. 静态路由(Static routing),一种路由的方式,路由项(routing ent

asp.net mvc 3.0 知识点整理 ----- (2).Controller中几种Action返回类型对比

通过学习,我们可以发现,在Controller中提供了很多不同的Action返回类型.那么具体他们是有什么作用呢?它们的用法和区别是什么呢?通过资料书上的介绍和网上资料的查询,这里就来给大家列举和大致的概括下. (1). ActionResult(base):最基本的Action类型,返回其他类型都可以写ActionResult. (2). ContentResult:返回ContentResult用户定义的内容类型. public ActionResult Content() { return

ASP.NET Web API路由系统:路由系统的几个核心类型

虽然ASP.NET Web API框架采用与ASP.NET MVC框架类似的管道式设计,但是ASP.NET Web API管道的核心部分(定义在程序集System.Web.Http.dll中)已经移除了对System.Web.dll程序集的依赖,实现在ASP.NET Web API框架中的URL路由系统亦是如此.也就是说,ASP.NET Web API核心框架的URL路由系统与ASP.NET本身的路由系统是相对独立的.但是当我们采用基于Web Host的方式(定义在程序集System.Web.H