2.2WebApi路由在Action上
这篇文章描述 ASP.NET Web API 如何将 HTTP 请求路由到特定的操作在控制器上。
有关路由的高级别概述,请参见ASP.NET Web API 的路由.
本文着眼于路由进程的详细信息。如果你创建一个 Web API 项目并发现一些请求不要路由你期望的方式,希望这篇文章将帮助。
路由具有三个主要阶段 ︰
- 匹配的 URI 到工艺路线模板。
- 选择一个控制器。
- 选择操作。
您可以用您自己的自定义行为替换一些零件的过程。在本文中,我描述的默认行为。最后,我注意到的地方,在那里你可以自定义的行为。
工艺路线模板
工艺路线模板看起来类似于 URI 路径,但它可以有占位符值,用花括号表示 ︰
"api/{controller}/public/{category}/{id}"
当你创建一个路由时,您可以为部分或全部的占位符提供默认值 ︰
您还可以提供约束,限制如何 URI 段可以匹配一个占位符 ︰
框架会尝试匹配模板的 URI 路径中的段。在模板中的文本必须完全匹配。占位符匹配任何价值,除非你指定的约束。框架与其他部分的 URI,如主机名或查询参数不匹配。框架将匹配 URI 路由表中选择的第一个路由。
有两个特别占位符:"{控制器}"和"{}"。
- "{}"控制器提供的控制器的名称。
- "行动 》 {}"提供的操作的名称。在 Web API 中,通常的约定是省略"的行动 {}"。
默认值
如果您提供默认值,该路由将与匹配 URI,它缺少这些段。例如 ︰
"Http://localhost/api/products"URI 匹配这条路线。"{类别}"段分配的默认值"全部"。
路由字典
如果框架找到了匹配的 URI,它会创建一个字典,包含为每个占位符的值。键是占位符名称,不包括大括号。这些值被从 URI 路径或默认值。这本词典存储在IHttpRouteData对象中。
在此路由匹配的阶段,特别"{}"控制器和"的行动 {}"占位符治疗就像其他占位符。它们只存储在字典中,其他值。
默认情况下可以有RouteParameter.Optional的特殊价值。如果占位符获取指定此值,值不是添加到路由字典。例如 ︰
对于"api/产品"的 URI 路径,路由字典将包含 ︰
- 控制器:"产品"
- 类别:"所有人"
然而,对于"api/产品/玩具/123",路由字典将包含 ︰
- 控制器:"产品"
- 类别:"玩具"
- id:"123"
默认设置也可以在路线模板中包含一个值未在任何地方出现。如果该路由匹配,该值存储在字典中。例如 ︰
如果 URI 路径是"api/根/8",这本字典将包含两个值 ︰
- 控制器:"客户"
- id:"8"
选择控制器
由IHttpControllerSelector.SelectController方法处理控制器所选内容。此方法采用HttpRequestMessage的实例,并返回HttpControllerDescriptor。由DefaultHttpControllerSelector类提供默认实现。此类使用一种简单的算法 ︰
- 在路由字典键"控制器"中查找。
- 采取此键的值和追加字符串"控制器",得到控制器的类型名称。
- 寻找与此类型名称的 Web API 控制器。
例如,如果路由字典包含键-值对"控制器"="产品",然后是控制器的类型是"ProductsController"。如果没有匹配的类型或多个匹配项,框架向客户端返回错误。
步骤 3, DefaultHttpControllerSelector使用IHttpControllerTypeResolver接口获取 Web API 控制器类型的列表。IHttpControllerTypeResolver的默认实现返回所有的公共类的 (a) 执行IHttpController,(b) 是不抽象,和 (c) 有一个名称,在"控制器"中结束。
选择动作
选择控制器后, 框架通过调用IHttpActionSelector.SelectAction方法将选择的行动。此方法采用HttpControllerContext并返回HttpActionDescriptor.
由ApiControllerActionSelector类提供默认实现。若要选择一个动作,它看起来在以下 ︰
- 请求的 HTTP 方法。
- 在工艺路线模板中,如果存在"的行动 {}"占位符。
- 在控制器上的操作的参数。
选择算法之前,我们需要了解一些控制器操作的东西。
在控制器上的方法被视为"行动"?当选择某个操作,框架只是看看公共实例方法的控制器上。此外,它排除了"特别的名字"方法 (构造函数、 事件、 运算符重载,等等),和从继承的方法ApiController类。
的 HTTP 方法。框架只选择匹配的要求,确定如下的 HTTP 方法的行为 ︰
- 您可以使用属性指定的 HTTP 方法 ︰ AcceptVerbs、 HttpDelete、公共、 HttpHead、 HttpOptions、 HttpPatch、 HttpPost或HttpPut.
- 否则,如果控制器方法的名称以"Get"、"开机自检"、"放"、"删除"、"头"、"选项"或"修补程序"开头,然后由公约行动支持的 HTTP 方法。
- 如果以上都不是,该方法支持邮政。
参数绑定。参数绑定是如何 Web API 创建参数的值。参数绑定的默认规则是这样的 ︰
- 简单类型是采取从 URI。
- 复杂类型是取自请求正文。
简单类型包括所有的.NET 框架基元类型,加上日期时间、十进制、 Guid,字符串和时间跨度。为每个操作,顶多一个参数可以读取请求正文。
它是可以重写默认绑定规则。请参见WebAPI 参数绑定引擎盖下.
与这种背景下,这里是行动选择算法。
- 在匹配的 HTTP 请求方法的控制器上创建的所有操作的列表。
- 如果路由字典有的"操作"项,删除其名称与此值不匹配的操作。
- 尝试匹配到的 URI,操作参数,如下所示 ︰
- 为每个操作,得到是一个简单的类型,其中绑定从 URI 获取参数的参数的列表。排除的可选参数。
- 从该列表中,试着找到适合每个参数的名称,或者路由字典或 URI 的查询字符串中。匹配项是区分大小写,并不依赖于参数顺序。
- 选择列表中的每个参数在 URI 匹配操作。
- 如果更多这一行动符合这些标准,挑选一个有大多数的参数匹配。
- 忽略[侵权]属性的行动。
步骤 #3 是最容易混淆的。其基本思想是一个参数可以获取其值,从 URI,从请求正文中,或从自定义绑定。对于来自 URI 的参数,我们想要确保 URI 实际上包含该路径 (通过路由字典) 中或在查询字符串中的参数的值。
例如,请考虑以下行动 ︰
Id参数绑定到的 URI。因此,这一行动只能匹配一个 URI,它包含"身份证号",在路由字典或查询字符串中的值。
可选参数是个例外,因为它们是可选的。为可选的参数,它是确定如果绑定不能从 URI 中获取价值。
复杂类型是个例外,出于不同的原因。复杂类型通过自定义绑定只能绑定到的 URI。但在这种情况下,框架不能预先知道是否该参数会绑定到特定的 URI。为了找到答案,它将需要调用绑定。选择算法的目标是从静态描述,在调用任何绑定之前选择的操作。因此,复杂类型被排除的匹配算法。
选择操作后,所有的参数绑定调用。
摘要 ︰
- 行动必须匹配请求的 HTTP 方法。
- 如果目前操作名称必须匹配路由字典中的"行动"条目。
- 为每个参数的作用,如果该参数是从 URI,然后参数名称必须找到路由字典或 URI 的查询字符串中。(可选参数和复杂类型的参数除外。)
- 尝试匹配最多的参数。最佳匹配可能是一种不带任何参数的方法。
扩展的示例
路线 ︰
routes.MapHttpRoute(
name: "ApiRoot",
routeTemplate: "api/root/{id}",
defaults: new { controller = "products", id = RouteParameter.Optional }
);
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
控制器 ︰
public class ProductsController : ApiController
{
public IEnumerable<Product> GetAll() {}
public Product GetById(int id, double version = 1.0) {}
[HttpGet]
public void FindProductsByName(string name) {}
public void Post(Product value) {}
public void Put(int id, Product value) {}
}
HTTP 请求 ︰
GET http://localhost:34701/api/products/1?version=1.5&details=1
路由匹配
URI 与路由匹配的名为"DefaultApi"。路由字典包含以下项 ︰
- 控制器:"产品"
- id:"1"
路由字典不包含查询字符串参数、"版本"和"详细信息",但这些仍被视为在行动选择。
控制器所选内容
从路由字典中的"控制器"条目,控制器类型是ProductsController.
选择动作
HTTP 请求是 GET 请求。支持 GET 的控制器行为是GetAll、 GetById和FindProductsByName。路由字典不包含"行动"的条目,所以我们不需要匹配的操作名称。
接下来,我们尝试匹配参数名称的操作,只看得到的行动。
| 行动 | 匹配的参数 |
|---|---|
GetAll |
没有一个 |
GetById |
""id |
FindProductsByName |
"名称" |
请注意,不是GetById的版本参数,因为它是一个可选的参数。
GetAll方法匹配琐细。GetById方法也相匹配,因为路由字典包含"id"。FindProductsByName方法不匹配。
GetById方法赢了,因为它与一个参数,与GetAll没有参数相匹配。用下面的参数值调用该方法 ︰
- id = 1
- 版本= 1.5
请注意,即使在选择算法不使用版本,参数的值来自 URI 的查询字符串。
扩展点
Web API 的某些部件中的路由选择进程提供了扩展点。
为任何这些接口提供自己的实现,请使用HttpConfiguration对象上的服务集合 ︰
2.2WebApi路由在Action上的更多相关文章
- 爱上MVC3~在控制器或Action上动态设定模板页(Layout)
回到目录 很多境况下,我们需要设置自己模块的layout,即它的布局页面,在MVC2中叫它模板页面,你可以在return view方法时设置它,当然,这不是一种好方法,因为我不想每个action都去设 ...
- WebApi:路由和Action选择
译自:http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection ...
- struts2,action上传文件
通过servlet实现文件上传,可以用用servlet接受到request的值的话:主要是这句话 List<?> items = upload.parseRequest(request); ...
- vue-router 获得上一级路由以及返回上一级路由的方法
if (this.$store.state.previousRouter.name) { this.$router.push({name: this.$store.state.previousRout ...
- 首页重定位到mian.action上
<body onload="top.location.href='<%=request.getContextPath()%>/main.action';">
- asp.net core的授权过滤器中获取action上的Attribute
var action = context.ActionDescriptor as ControllerActionDescriptor; var permission = action.MethodI ...
- MVC POST在ACTION上进行多个模型的数据绑定
首先声明,接下来的东西并不符合本人认同的严谨的MVC模式. 用MVC做项目的过程中,越来越多的用到不严谨的MVC编程. 比如,在"cshtml"文件中写: @Html.Raw(DB ...
- 工作总结 [ActionName("ss123")] 更改路由中Action名称 获取或设置操作的名称
- 解读ASP.NET 5 & MVC6系列(11):Routing路由
新版Routing功能介绍 在ASP.NET 5和MVC6中,Routing功能被全部重写了,虽然用法有些类似,但和之前的Routing原理完全不太一样了,该Routing框架不仅可以支持MVC和We ...
随机推荐
- 小讲堂:在线编辑在Mobox文档管理软件中的意义
今天我们来讨论一下,mobox文档管理软件中的在线编辑的这个功能,相信这个功能是用户在日常的文档维护中非常需要的. 文档管理软件的诸多功能中,在线编辑是一块很重要的功能点,因为在线编辑可以说是提高工作 ...
- C# ASP.NET 优化程序性能、降低内存使用、提高程序运行速度
首先纪念一下今天的股票大跌抓个图,虽然我自己损失不是很大,但是应该大多人都损失不小.也可能有人会继续跳楼,也可能是股市一个新的转折点来了. 接着还是重点关注自己写代码优化的主题吧.软件系统当访问量不大 ...
- C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 面向全国标准省市县行政数据基础之上的组织机构管理
由于信息系统庞大.各种业务子系统.各种开发语言开发的业务逻辑.各种年代维护的代码.各种参差不齐的历史遗留信息系统,面向全国的业务系统,面向某个领域的汽运管理信息系统,面向内部的业务系统,面向外部的各种 ...
- CSS实现背景透明,文字不透明(兼容各浏览器)
在 FF/Chrome 等较新的浏览器中可以使用css属性background- color的rgba轻松实现背景透明,而文字保持不透明.而IE6/7/8浏览器不支持rgba,只有使用IE的专属滤镜f ...
- 1122MySQL性能优化之 Nested Loop Join和Block Nested-Loop Join(BNL)
转自http://blog.itpub.net/22664653/viewspace-1692317/ 一 介绍 相信许多开发/DBA在使用MySQL的过程中,对于MySQL处理多表关联的方式或者说 ...
- 【USACO 2.4】Cow Tours (最短路)
题意:给你n(最多150)个点的坐标,给出邻接矩阵,并且整个图至少两个联通块,现在让你连接一条边,使得所有可联通的两点的最短距离的最大值最小. 题解:先dfs染色,再用floyd跑出原图的直径O($n ...
- Android网络文件下载模块整理
一.知识基础 tomcat服务器配置 理解http协议 理解javaIO操作相关知识 SDcard操作知识 Android 权限配置 二.实现步骤 1.从网上获取资源 public String do ...
- python 中文乱码问题2
1.文件存为utf-8的格式,windows和linux两个环境都可以用 2.中文输出可以采用u方法 比如:print u'成年'
- 初识Jsoup之解析HTML
按照国际惯例,我首先应该介绍下Jsoup是个什么东西,然后在介绍下具体用法,然后在来个demo演示,其实我也是这么想的,小编今天花了一天的时间从学习—>解析页面,总算是成果圆满了吧,啊哈,但是, ...
- php实现转换html格式为文本格式的方法
有时候需要转换html格式的字符串为文本,但又需要保持一定的格式,比如要求段落变成的分段格式就可以用下面这个函数 function html2text($str){ $str = preg_repl ...