ASP.NET Core中自定义路由约束的实现
路由约束
asp.net core中,通过定义路由模板,可以在url上传递变量,同时可以针对变量提供默认值、可选和约束。
约束的使用方法是在属性路由上添加指定的约束名,用法如下:
// 单个使用 [route("users/{id:int}")] public user getuserbyid(int id) { } // 组合使用 [route("users/{id:int:min(1)}")] public user getuserbyid(int id) { }
框架内部已经提供了一些约束,如下所示:
约束 | 示例 | 匹配项示例 | 说明 |
---|---|---|---|
int | {id:int} | 123456789, -123456789 | 匹配任何整数 |
bool | {active:bool} | true, false | 匹配 true或 false(区分大小写) |
datetime | {dob:datetime} | 2016-12-31, 2016-12-31 7:32pm | 匹配有效的 datetime 值(位于固定区域性中 - 查看警告) |
decimal | {price:decimal} | 49.99, -1,000.01 | 匹配有效的 decimal 值(位于固定区域性中 - 查看警告) |
double | {weight:double} | 1.234, -1,001.01e8 | 匹配有效的 double 值(位于固定区域性中 - 查看警告) |
float | {weight:float} | 1.234, -1,001.01e8 | 匹配有效的 float 值(位于固定区域性中 - 查看警告) |
guid | {id:guid} | cd2c1638-1638-72d5-1638-deadbeef1638, {cd2c1638-1638-72d5-1638-deadbeef1638} | 匹配有效的 guid 值 |
long | {ticks:long} | 123456789, -123456789 | 匹配有效的 long 值 |
minlength(value) | {username:minlength(4)} | rick | 字符串必须至少为 4 个字符 |
maxlength(value) | {filename:maxlength(8)} | richard | 字符串不得超过 8 个字符 |
length(length) | {filename:length(12)} | somefile.txt | 字符串必须正好为 12 个字符 |
length(min,max) | {filename:length(8,16)} | somefile.txt | 字符串必须至少为 8 个字符,且不得超过 16 个字符 |
min(value) | {age:min(18)} | 19 | 整数值必须至少为 18 |
max(value) | {age:max(120)} | 91 | 整数值不得超过 120 |
range(min,max) | {age:range(18,120)} | 91 | 整数值必须至少为 18,且不得超过 120 |
alpha | {name:alpha} | rick | 字符串必须由一个或多个字母字符(a-z,区分大小写)组成 |
regex(expression) | {ssn:regex(^\d{{3}}-\d{{2}}-\d{{4}}$)} | 123-45-6789 | 字符串必须匹配正则表达式(参见有关定义正则表达式的提示) |
required | {name:required} | rick | 用于强制在 url 生成过程中存在非参数值 |
内置的约束能够适用于大部分常见的应用场景,但是有时候我们还是需要去自定义我们想要的效果。
自定义路由约束
自定义约束是要实现 irouteconstraint 接口,然后重载 match 方法,该方法有四个参数。
第一个参数 httpcontext 是当前请求的上下文
第二个参数 route 是当前约束所属的路由
第三个参数 routekey 是当前检查的变量名,例如文章开头示例中的 id
第四个参数 values 是当前url匹配的字典值,例如文章开头的示例的路由,如果url是 users/1 ,那么就有一个字典,其 key = id , value = 1 。当然还有其他的变量的值,比如 controller , action 等。
第五个参数 routedirection 是一个枚举值,代表是web请求的还是用 url.action 等方法生成url。
举一个实例,我们想要定义一个约束,指定路由传过来的参数必须是指定的枚举值。
我们先定义一个枚举:
public enum boolenum { true, false }
然后定义约束:
public class enumconstraint : irouteconstraint { private type _enumtype; public enumconstraint(string enumtypename) { _enumtype = type.gettype(enumtypename); } public bool match(httpcontext httpcontext, irouter route, string routekey, routevaluedictionary values, routedirection routedirection) { var value = values[routekey]; if (value == null) { return false; } if (enum.tryparse(_enumtype, value.tostring(), out object result)) { if (enum.isdefined(_enumtype, result)) { return true; } } return false; } }
在 startup.cs 的 configureservices 方法添加自定义约束:
services.configure<routeoptions>(options => { options.constraintmap.add("enum", typeof(enumconstraint)); });
在路由上使用约束:
( webapplicationtest 是当前的 namespace )
[route("api/[controller]")] [apicontroller] public class testcontroller : controllerbase { // get: api/test [httpget("{bool:enum(" + nameof(webapplicationtest) + "." + nameof(boolenum) + ")}")] public string get(boolenum @bool) { return "bool: " + @bool; } [httpget("{id:int:min(2)}", name = "get")] public string get(int id) { return "id: " + id; } [httpget("{name}")] public string get(string name) { return "name: " + name; } }
{id:int:min(2)} 路由必须使用 min(2) ,否则对于 id = 0 或 id = 1 会有冲突。
运行程序,当路由是 api/test/0 、 api/test/1 、 api/test/true 和 api/test/false 的时候,匹配我们的自定义约束。
当路由是 api/test/{大于2的整数} 的时候,匹配第二个路由。
其他情况匹配第三个路由。
结论
路由约束在某些场景下是非常有用的功能,可以减少 controller 中校验参数,将部分参数校验的功能使用声明式的 attruibute 来实现,某些重复的校验可以通过抽取成约束公共使用。
constraint 的构造函数可以使用注入,所以可以扩展性十分强,可以通过查询数据库做一些参数校验。
官网上对于路由约束只是简单的提了一下,本文对路由约束的使用提供了具体的示例。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: C#中事务处理和非事务处理方法实例分析
下一篇: xmind思维导图怎么搜索内容?
推荐阅读
-
ASP.NET Core 2.2中的Endpoint路由详解
-
ASP.NET Core中自定义路由约束的实现
-
详解ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁
-
Asp.Net Core中基于Session的身份验证的实现
-
ASP.NET Core MVC 中实现中英文切换的示例代码
-
ASP.net中Core自定义View查找位置的实例代码
-
浅谈如何在ASP.NET Core中实现一个基础的身份认证
-
在ASP.NET Core中实现一个Token base的身份认证实例
-
在ASP.NET Core中显示自定义的错误页面
-
如何在Asp.Net Core MVC中处理null值的实现