[水煮 ASP.NET Web API2 方法论](3-5)路由约束
问题
怎么样限制路由中参数的值。
解决方案
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()}
},
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 Web API2 方法论](3-5)路由约束的更多相关文章
- [水煮 ASP.NET Web API2 方法论](3-9)空气路由的设置
阅读导航 问题 解决方案 工作原理 代码演示 在此解释一下,空气路由,是本人臆想出来,觉着更能表达 IgnoreRoute 的意图,如果看着辣眼睛^^,请见谅. 问题 我们在之定义过集中式路由,集中式 ...
- [水煮 ASP.NET Web API2 方法论](3-4)设置路由可选项
问题 怎么样创建一个路由,不管客户端传不传这个参数,都可以被成功匹配. 解决方案 ASP.NET WEB API 的集中式路由和属性路由都支持路由声明可选参数. 在用集中式路由中可以通过 RouteP ...
- [水煮 ASP.NET Web API2 方法论](3-1)集中式路由
问题 怎样集中的定义路由 解决方案 通过调用 HttpRouteCollectionExtension 类中的 MapHttpRoute 扩展方法在 HttpRouteCollection 中定义路由 ...
- [水煮 ASP.NET Web API2 方法论](1-1)在MVC 应用程序中添加 ASP.NET Web API
问题 怎么样将 Asp.Net Web Api 加入到现有的 Asp.Net MVC 项目中 解决方案 在 Visual Studio 2012 中就已经把 Asp.Net Web Api 自动地整合 ...
- [水煮 ASP.NET Web API2 方法论](1-5)ASP.NET Web API Scaffolding(模板)
问题 我们想快速启动一个 ASP.NET Web API 解决方案. 解决方案 APS.NET 模板一开始就支持 ASP.NET Web API.使用模板往我们的项目中添加 Controller,在我 ...
- [水煮 ASP.NET Web API2 方法论](3-8)怎样给指定路由配置处理器
阅读导航 问题 解决方案 工作原理 代码演示 问题 如果仅仅针对指定的路由进行某些特定的消息处理,而不是应用于所有路由,我们应该怎么做呢? 解决方案 ASP.NET WEB API 的很多功能都内建了 ...
- [水煮 ASP.NET Web API2 方法论](3-7)默认 Action 请求方式以及 NonActionAttribute
问题 在 Controller 中有一个 public 的方法,但是又不想将这个 publlic 方法暴露成为一个 API. 解决方案 ASP.NET Web API 中,正常是通过 HTTP 谓词来 ...
- [水煮 ASP.NET Web API2 方法论](3-6)万能路由
问题 定义什么样的路由,可以不会受请求参数类型和数量的限制,而被全部捕获? 解决方案 在路由模板中,给参数添加一个"*"前缀,例如 {*param},只要请求的 URL 能够和路由 ...
- [水煮 ASP.NET Web API2 方法论](3-3)路由默认值
问题 如何为路由中参数设置默认值. 解决方案 不管使用属性路由还是集中式路由,ASP.NET WEB API 都可以很方便的为路由定义默认参数.在每次客户端请求的时候,如果客户端没有传这些参数,框架会 ...
随机推荐
- AWVS漏洞测试-02节-添加一个简单的新闻系统
实现一个简单的新闻发布系统 有登录 注册 添加新闻 浏览新闻 评论新闻 新闻列表 这些基本功能 使用asp.net webform 首先是登录页 protected void Button1_Clic ...
- Windows下安装 msysGit 以及初始化 Git server环境
Windows下git工具msysGit使用以及Git server初始化 Windows下git工具,这里选择msysGit,版本为msysGit-netinstall-1.8.1.2-previe ...
- CSS3学习笔记--line-height:150%与line-height:1.5的真正区别
代码: <div style="line-height:150%;font-size:16px;"> 父元素内容 <div style="font-si ...
- Android NDK 同时编译多个Module
LOCAL_PATH := $(call my-dir) ## ## NDK 支持同时编译多个Module: ## 在配置的时候,每个Module需要 以 include $(CLEAR_VARS)开 ...
- LoadRunner场景参数文件部分参数说明(我在某银行的整理)
由于场景中脚本繁多,同时设置60个脚本的“运行时设置”会提示个数限制信息,这时可以考虑通过场景的参数文件配置来批量解决这些事情,主要是提高工作效率. 选中自己保存的controller场景,鼠标右键点 ...
- 通过PowerShell获取Windows系统密码Hash
当你拿到了系统控制权之后如何才能更长的时间内控制已经拿到这台机器呢?作为白帽子,已经在对手防线上撕开一个口子,如果你需要进一步扩大战果,你首先需要做的就是潜伏下来,收集更多的信息便于你判断,便于有更大 ...
- searchableselect不支持onchange的问题
1.找到jquery.searchableSelect.js 2.找到selectItem函数 修改里面的方法,加入自定义你要回调的函数 selectItem: function(item){ //L ...
- Js 一些方法(一)
(function ($) { var promoter = promoter || {}; promoter.utils = (function () { var controller = &quo ...
- cocos2dx在ubuntu下配置声音引擎
声音引擎库和cocos2dx的库是分开的我们要使用的时候不得不重新修改一下makefile,首先我们要找到声音引擎库的位置,在cocos2dx的 根目录下有一个lib文件,看一下是否存在libcoco ...
- svn diff excel
https://github.com/solq360/compareExcel jdk 1.7 可自己编译1.6 每个sheet第一行不允许为空 SVN对比excel差异 适合策划.财务职业使用 sv ...