[水煮 ASP.NET Web API2 方法论](3-5)路由约束
2016-12-08 08:02
435 查看
问题
怎么样限制路由中参数的值。
解决方案
ASP.NET WEB API 允许我们通过 IHttpRouteConstraint 接口设置路由约束。集中式路由和直接式路由都可以使用 IHttpRouteConstraint。
框架提供了 18 个接口,他提供了大部分类型的约束,例如,路由参数长度相关的约束,可以确保值都在定义范围内,或者限制数据类型。当然也可以通过实现接口 IHttpRouteConstraint 来自定义约束逻辑。
工作原理
IHttpRoutConstraint 是一个 HTTP 路由约束接口(如代码片段 3-11),并公开了一个简单的方法 Match,这个方法需要五个参数,HttpRequestMessage 实例,IHttpRoute 实例,string 类型的 parameterName,Idictionary<string,object> 类型的路由 value,HttpRouteDirection 类型的 routeDirection,也是为了保证路由可以基于应用程序的逻辑被匹配到。
代码片段 3-11 IHttpRouteConstraint 定义
也可以通过使用 CompoundRouteConstraint 进行复合约束,需要通过构造函数添加到 IHttpRouteConstraint 集合中,如表格 3-1 所示,展示内建的约束和基本用法
表格 3-1. ASP.NET WEB API 中 IHttpRouteConstraint 可以用的约束
属性路由,是通过 DefaultInlineConstraintResolver 来映射嵌入约束的版本和实际类型。当调用 MapHttpAtrributeRoute 的时候,ASP.NET WEB API 会使用解析器转换嵌入约束为相关 IHttpRouteConstraint 实例。为了采用某些约束处理自定义约束,也可以修改 DefaultInlineConstraintResolver 或者自己实现全部的 IInineConstraintReslover 接口。不管怎么样,都需要传一个他的实例给方法 MapHttpAttributeRoute。
OptionalRouteConstraint 是被用来提供可选参数功能的,如上一篇 3-4 介绍的,还提供了常见的约束功能。如果路由参数不是 RouteParameter.Optional 的,OptionalRouteConstraint 就只会计算约束。
代码演示
对于集中式路由,约束是作为 MapHttpRoute 方法的第三个参数传进来的。与默认值类似,已经在 3-3 部分介绍过,这个参数的类型是 Idictionary<string,object>,但是,框架的设计也是可以传匿名对象,这个方法签名的实际类型就是一个简单对象。约束参数的名称必须和路由模板以及 Action 的签名一致。
使用集中式路由,也可以定义一个字符串的嵌入正则表达式,不必使用任何 IHttpRouteConstarint 接口。在下面的李子中,“id”就是一个数字约束嵌入正则表达式。
集中式路由也可以约束 HTTP 方法,只要通过一个预定义的 httpMethod 键并赋值 HttpMethodConstrtin 就可以。
对于直接式路由,可以通过在参数加上冒号再加上约束条件。
对于复合路由的定义,集中式路由需要通过 CompoundRouteConstraint 转换。
对于属性路由,可以通过冒号将不同的约束链起来;框架会在内部使用 CompoundRouteConstraint 构建复合约束。
一个简单的自定义路由约束,确保参数是一个合法的 email 格式,如代码片段 3-12 所示。因为路由值是 IDictionary<string.object>,再验证约束之前需要转换成期望的类型(这里就是 string)。
直接在集中式路由中,像使用内置约束一样使用这个约束。
然而,使用属性路由的时候,可以使用别名来代替,但是在 EmailRouteConstraint 类没有这样的定义。因为,别名和约束类型是通过 DefaultInlineConstraintReslover 来完成映射的,ASP.NET WEB API 使用这个来解析这个约束,我们需要执行如下步骤
这样,就可以像使用框架提供的约束一样,使用上面定义的 email 约束。
注意 如果没有额外的映射步骤,约束就不会有任何反应,但是,ASP.NET WEB API 的整个属性路由可能有问题。
怎么样限制路由中参数的值。
解决方案
ASP.NET WEB API 允许我们通过 IHttpRouteConstraint 接口设置路由约束。集中式路由和直接式路由都可以使用 IHttpRouteConstraint。
框架提供了 18 个接口,他提供了大部分类型的约束,例如,路由参数长度相关的约束,可以确保值都在定义范围内,或者限制数据类型。当然也可以通过实现接口 IHttpRouteConstraint 来自定义约束逻辑。
工作原理
IHttpRoutConstraint 是一个 HTTP 路由约束接口(如代码片段 3-11),并公开了一个简单的方法 Match,这个方法需要五个参数,HttpRequestMessage 实例,IHttpRoute 实例,string 类型的 parameterName,Idictionary<string,object> 类型的路由 value,HttpRouteDirection 类型的 routeDirection,也是为了保证路由可以基于应用程序的逻辑被匹配到。
代码片段 3-11 IHttpRouteConstraint 定义
public interface IHttpRouteConstraint { bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection); }
也可以通过使用 CompoundRouteConstraint 进行复合约束,需要通过构造函数添加到 IHttpRouteConstraint 集合中,如表格 3-1 所示,展示内建的约束和基本用法
表格 3-1. ASP.NET WEB API 中 IHttpRouteConstraint 可以用的约束
属性路由,是通过 DefaultInlineConstraintResolver 来映射嵌入约束的版本和实际类型。当调用 MapHttpAtrributeRoute 的时候,ASP.NET WEB API 会使用解析器转换嵌入约束为相关 IHttpRouteConstraint 实例。为了采用某些约束处理自定义约束,也可以修改 DefaultInlineConstraintResolver 或者自己实现全部的 IInineConstraintReslover 接口。不管怎么样,都需要传一个他的实例给方法 MapHttpAttributeRoute。
OptionalRouteConstraint 是被用来提供可选参数功能的,如上一篇 3-4 介绍的,还提供了常见的约束功能。如果路由参数不是 RouteParameter.Optional 的,OptionalRouteConstraint 就只会计算约束。
代码演示
对于集中式路由,约束是作为 MapHttpRoute 方法的第三个参数传进来的。与默认值类似,已经在 3-3 部分介绍过,这个参数的类型是 Idictionary<string,object>,但是,框架的设计也是可以传匿名对象,这个方法签名的实际类型就是一个简单对象。约束参数的名称必须和路由模板以及 Action 的签名一致。
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "orders/{text}", constraints: new {text = new AlphaRouteConstraint()}, defaults: null );
使用集中式路由,也可以定义一个字符串的嵌入正则表达式,不必使用任何 IHttpRouteConstarint 接口。在下面的李子中,“id”就是一个数字约束嵌入正则表达式。
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "size/{id}", constraints: new {id = "\d+"}, defaults: null );
集中式路由也可以约束 HTTP 方法,只要通过一个预定义的 httpMethod 键并赋值 HttpMethodConstrtin 就可以。
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "size/{id}", constraints: new {httpMethod = new HttpMethodConstraint(HttpMethod.Get)}, defaults: null );
对于直接式路由,可以通过在参数加上冒号再加上约束条件。
[Route("orders/{text:alpha}")] public HttpResponseMessage Get(string text){}
对于复合路由的定义,集中式路由需要通过 CompoundRouteConstraint 转换。
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "orders/{text}", constraints: new { text = new CompoundRouteConstraint(new List<IHttpRouteConstraint> {new AlphaRouteConstraint(), new MaxLengthRouteConstraint(5)} }, defaults: null );
对于属性路由,可以通过冒号将不同的约束链起来;框架会在内部使用 CompoundRouteConstraint 构建复合约束。
[Route("orders/{text:alpha:maxlength(5)}")] public HttpResponseMessage Get(string text){}
一个简单的自定义路由约束,确保参数是一个合法的 email 格式,如代码片段 3-12 所示。因为路由值是 IDictionary<string.object>,再验证约束之前需要转换成期望的类型(这里就是 string)。
public class EmailRouteConstraint : IHttpRouteConstraint { public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection) { object value; if (values.TryGetValue(parameterName, out value) && value != null) { var stringValue = value as string; if (stringValue == null) return false; try { var email = new MailAddress(stringValue); return true; } catch (FormatException) { return false; } } return false; } }
直接在集中式路由中,像使用内置约束一样使用这个约束。
config.Routes.MapHttpRoute( name: "Email", routeTemplate: "{controller}/email/{text}", constraints: new {text = new EmailRouteConstraint()}, defaults: null );
然而,使用属性路由的时候,可以使用别名来代替,但是在 EmailRouteConstraint 类没有这样的定义。因为,别名和约束类型是通过 DefaultInlineConstraintReslover 来完成映射的,ASP.NET WEB API 使用这个来解析这个约束,我们需要执行如下步骤
var constraintResolver = new DefaultInlineConstraintResolver(); constraintResolver.ConstraintMap.Add("email", typeof (EmailRouteConstraint)); config.MapHttpAttributeRoutes(constraintResolver);
这样,就可以像使用框架提供的约束一样,使用上面定义的 email 约束。
[Route("orders/client/{text:email}")] public HttpResponseMessage GetByClient(string text) { }
注意 如果没有额外的映射步骤,约束就不会有任何反应,但是,ASP.NET WEB API 的整个属性路由可能有问题。
相关文章推荐
- ASP.NET Core File Providers
- CRM HomePage.aspx
- ASP.NET Web API上实现 Web Socket
- asp.net
- asp.net大文件上传与上传文件进度条问题
- AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案
- gridview的属性
- Asp.net中GridView使用详解
- ASP.NET MVC的过滤器
- 深入理解面向切面的编程AOP、AspectJ、Spring
- Metasploit - ERROR: cannot discover where libxml2 is located on your system
- 详解ASP.NET Core应用中如何记录和查看日志
- [Asp.net]最全的WebBrowser使用帮助案例
- VS2015 搭建Asp.net core开发环境的方法
- OWASP ZAP上手体验
- ASP.NET编程中经常用到的27个函数集
- 浅谈ASP.NET中多层架构
- 详解ASP.NET MVC的筛选器
- [ASP.NET] SQL SERVER 统计一天24小内的交易量 编辑:吴立星
- [Asp.Net MVC4]验证用户登录实现实例