这篇文章描述 ASP.NET Web API 如何将 HTTP 请求路由到特定的操作在控制器上。

有关路由的高级别概述,请参见ASP.NET Web API 的路由.

本文着眼于路由进程的详细信息。如果你创建一个 Web API 项目并发现一些请求不要路由你期望的方式,希望这篇文章将帮助。

路由具有三个主要阶段 ︰

  1. 匹配的 URI 到工艺路线模板。
  2. 选择一个控制器。
  3. 选择操作。

您可以用您自己的自定义行为替换一些零件的过程。在本文中,我描述的默认行为。最后,我注意到的地方,在那里你可以自定义的行为。

工艺路线模板

工艺路线模板看起来类似于 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类提供默认实现。此类使用一种简单的算法 ︰

  1. 在路由字典键"控制器"中查找。
  2. 采取此键的值和追加字符串"控制器",得到控制器的类型名称。
  3. 寻找与此类型名称的 Web API 控制器。

例如,如果路由字典包含键-值对"控制器"="产品",然后是控制器的类型是"ProductsController"。如果没有匹配的类型或多个匹配项,框架向客户端返回错误。

步骤 3, DefaultHttpControllerSelector使用IHttpControllerTypeResolver接口获取 Web API 控制器类型的列表。IHttpControllerTypeResolver的默认实现返回所有的公共类的 (a) 执行IHttpController,(b) 是不抽象,和 (c) 有一个名称,在"控制器"中结束。

选择动作

选择控制器后, 框架通过调用IHttpActionSelector.SelectAction方法将选择的行动。此方法采用HttpControllerContext并返回HttpActionDescriptor.

ApiControllerActionSelector类提供默认实现。若要选择一个动作,它看起来在以下 ︰

  • 请求的 HTTP 方法。
  • 在工艺路线模板中,如果存在"的行动 {}"占位符。
  • 在控制器上的操作的参数。

选择算法之前,我们需要了解一些控制器操作的东西。

在控制器上的方法被视为"行动"?当选择某个操作,框架只是看看公共实例方法的控制器上。此外,它排除了"特别的名字"方法 (构造函数、 事件、 运算符重载,等等),和从继承的方法ApiController类。

的 HTTP 方法。框架只选择匹配的要求,确定如下的 HTTP 方法的行为 ︰

  1. 您可以使用属性指定的 HTTP 方法 ︰ AcceptVerbs、 HttpDelete公共、 HttpHead、 HttpOptions、 HttpPatch、 HttpPostHttpPut.
  2. 否则,如果控制器方法的名称以"Get"、"开机自检"、"放"、"删除"、"头"、"选项"或"修补程序"开头,然后由公约行动支持的 HTTP 方法。
  3. 如果以上都不是,该方法支持邮政。

参数绑定。参数绑定是如何 Web API 创建参数的值。参数绑定的默认规则是这样的 ︰

  • 简单类型是采取从 URI。
  • 复杂类型是取自请求正文。

简单类型包括所有的.NET 框架基元类型,加上日期时间十进制、 Guid字符串时间跨度。为每个操作,顶多一个参数可以读取请求正文。

它是可以重写默认绑定规则。请参见WebAPI 参数绑定引擎盖下.

与这种背景下,这里是行动选择算法。

  1. 在匹配的 HTTP 请求方法的控制器上创建的所有操作的列表。
  2. 如果路由字典有的"操作"项,删除其名称与此值不匹配的操作。
  3. 尝试匹配到的 URI,操作参数,如下所示 ︰
    1. 为每个操作,得到是一个简单的类型,其中绑定从 URI 获取参数的参数的列表。排除的可选参数。
    2. 从该列表中,试着找到适合每个参数的名称,或者路由字典或 URI 的查询字符串中。匹配项是区分大小写,并不依赖于参数顺序。
    3. 选择列表中的每个参数在 URI 匹配操作。
    4. 如果更多这一行动符合这些标准,挑选一个有大多数的参数匹配。
  4. 忽略[侵权]属性的行动。

步骤 #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、 GetByIdFindProductsByName。路由字典不包含"行动"的条目,所以我们不需要匹配的操作名称。

接下来,我们尝试匹配参数名称的操作,只看得到的行动。

行动 匹配的参数
GetAll 没有一个
GetById ""id
FindProductsByName "名称"

请注意,不是GetById版本参数,因为它是一个可选的参数。

GetAll方法匹配琐细。GetById方法也相匹配,因为路由字典包含"id"。FindProductsByName方法不匹配。

GetById方法赢了,因为它与一个参数,与GetAll没有参数相匹配。用下面的参数值调用该方法 ︰

  • id = 1
  • 版本= 1.5

请注意,即使在选择算法不使用版本,参数的值来自 URI 的查询字符串。

扩展点

Web API 的某些部件中的路由选择进程提供了扩展点。

为任何这些接口提供自己的实现,请使用HttpConfiguration对象上的服务集合 ︰

2.2WebApi路由在Action上的更多相关文章

  1. 爱上MVC3~在控制器或Action上动态设定模板页(Layout)

    回到目录 很多境况下,我们需要设置自己模块的layout,即它的布局页面,在MVC2中叫它模板页面,你可以在return view方法时设置它,当然,这不是一种好方法,因为我不想每个action都去设 ...

  2. WebApi:路由和Action选择

      译自:http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection   ...

  3. struts2,action上传文件

    通过servlet实现文件上传,可以用用servlet接受到request的值的话:主要是这句话 List<?> items = upload.parseRequest(request); ...

  4. vue-router 获得上一级路由以及返回上一级路由的方法

    if (this.$store.state.previousRouter.name) { this.$router.push({name: this.$store.state.previousRout ...

  5. 首页重定位到mian.action上

    <body onload="top.location.href='<%=request.getContextPath()%>/main.action';">

  6. asp.net core的授权过滤器中获取action上的Attribute

    var action = context.ActionDescriptor as ControllerActionDescriptor; var permission = action.MethodI ...

  7. MVC POST在ACTION上进行多个模型的数据绑定

    首先声明,接下来的东西并不符合本人认同的严谨的MVC模式. 用MVC做项目的过程中,越来越多的用到不严谨的MVC编程. 比如,在"cshtml"文件中写: @Html.Raw(DB ...

  8. 工作总结 [ActionName("ss123")] 更改路由中Action名称 获取或设置操作的名称

  9. 解读ASP.NET 5 & MVC6系列(11):Routing路由

    新版Routing功能介绍 在ASP.NET 5和MVC6中,Routing功能被全部重写了,虽然用法有些类似,但和之前的Routing原理完全不太一样了,该Routing框架不仅可以支持MVC和We ...

随机推荐

  1. 发布和运行HOLOLENS程序注意这里要勾上,不然就成普通的UWP程序了!

  2. JSON 字符串中的中括号和大括号区别详解

    json 变量有两种可能, 可能是一个对象, (类似 类的实例), 也可能是一个数组!! 主要是要 从 ""语义" 上来分析, 到底该用 大括号还是用中括号: 如果从语义 ...

  3. 全国高校网安联赛Web专场~WriteUp

    1.Sign 题目:Good Luck!flag{X-nuca@GoodLuck!} Flag直接写在题目上了,flag{X-nuca@GoodLuck!} 2.BaseCoding 提示:这是编码不 ...

  4. Metasploit爆破tcpwrapped服务

    转自:http://www.mamicode.com/info-detail-1653722.html 一.利用nmap工具扫描目标主机 1.1 使用nmap命令对目标主机进行扫描. 1.2 在终端中 ...

  5. svg拉伸,原来凹凸可以这么玩

    原文:http://www.smartjava.org/content/render-geographic-information-3d-threejs-and-d3js The last coupl ...

  6. 系统修改利器XueTr

    Windows系统修改利器XueTr 周银辉 在Windows下如果遇到某些进程弄死结束不了,某些文件弄死删不掉,拷贝不出来 (可能是因为你没有管理员权限,可能是因为人家是病毒,可能是系统保护文件,可 ...

  7. jquery easyui 1.4.1 API( CHM版)

    ChangeLog Bug The combogrid has different height than other combo components. fixed. datagrid: The r ...

  8. python 环境搭建

    python下载地址: 进入https://www.python.org/download/releases/3.3.4/,下载Windows X86-64 MSI Installer (3.3.4) ...

  9. iOS——学习网址收集+如何提高iOS开发技能

    1 一个比系统自带的终端好用的软件:http://www.iterm2.com 2 学习和遇到技术问题可以去的网站: CocoaChina      http://developer.cocoachi ...

  10. 【jQuery】scroll 滚动到顶部

    Jquery 实现页面滚动到顶端 $(document).ready(function () { // 滚动窗口来判断按钮显示或隐藏 $(window).scroll(function () { // ...