WebApi-路由机制
一、WebApi路由机制是什么?
路由机制通俗点来说:其实就是WebApi框架将用户在浏览器中输入的Url地址和路由表中的路由进行匹配,并根据最终匹配的路由去寻找并匹配相应的Controller和Action并执行的一个过程。
从WebApi框架接收到来自外部环境的接口调用请求到指定接口的执行大概需要以下的匹配过程:1、匹配URL路由 2、Controller匹配 3、Action匹配
下面我么分别对这几个流程进行详细说明。
二、匹配URL路由
WebApi框架接收到来自外部的接口请求后,首先将路由表中的路由一条一条和Url地址进行匹配,一旦匹配上则不再继续往下匹配,如果匹配完了所有路由都未匹配上,则会报404错误。
如果成功匹配上指定路由,则框架根据路由的Url模板中指定的Controller的所在位置以及Action的所在位置从用户请求的Url中提取出将要调用的Controller的名称以及Action的名称,当然要被调用的Controller名或者Action名也可能不是从用户发起的接口调用请求Url中获得的,因为WebApi中在进行路由配置时提供了参数默认值的配置,也就是说Controller名或者Action名可能来源于路由配置时的默认值。
该流程结束后:WebApi框架将会从用户请求的接口调用URL中提取出用户想调用的接口所对应的Controller 、Action 、以及用户传给指定Action的参数(即路由数据)等等,
这些数据存储在了一个字典集合中,这个路由数据字典我们可以在Action方法中通过如下方式获得:
IHttpRouteData routeData = Request.GetRouteData();
IDictionary<string, object> routeDataValues = routeData.Values;
这里需要澄清的几点的是:
1、URL未匹配上任何路由 和 匹配上了路由但是未找到相应的Controller和Action 是两个不同的概念,IIS对这两种情况的响应是不一样的。
URL未匹配上路由:
如果用户请求的接口的地址不能和路由表中的所有路由相匹配,IIS将直接报告404错误。
匹配上了路由但未找到相应Controller或Action:
如果匹配上了路由但是未找到响应的Controller或Action,那么将报类似如下错误:

MessageDetail节点详细描述了是 Controller未找到还是 Action未找到。
2、由于路由表中可以配置一条或者多条路由,并且WebApi框架在匹配成功一条路由后将不再继续往下匹配,也就是说即使此时后面还有路由可以
和当前请求匹配也不会被匹配到,所以请务必注意每条路由的配置顺序,否则可能造成意想不到的结果。
如:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "TestRoute",
routeTemplate: "{controller}/{action}",
defaults: new { action = "Index" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
); }
假设我们此时代码中包含如下控制器和Action:
public class ValuesController : ApiController
{
public string Get()
{
return "value";
}
[HttpGet]
public object QueryValues(int index)
{
string[] strs = new string[] { "张三", "李四" };
if (index < || index >= strs.Length)
{
return JsonConvert.SerializeObject(strs);
}
return strs[index];
}
}
我们在浏览器中输入:http://localhost:16982/api/Values,会发现总是匹配到的是TestRoute这个路由,实际上我们只是想访问Values中的无参数的Get方法。

事实上,解决这个问题只需要将TestRoute路由的配置放到DefaultApi路由的后面即可。
三、Controller匹配
经过路由匹配后,框架已经从用户请求的Url中提取到需要访问的Controller名、Action名、以及在路由模板中定义的参数所对应的值等等,此时WebApi框架从路由数据字典中获取出键为:controller的值,在这个值的基础上去找类型名为 Controller名+Controller 结尾的类,此时如果找到相应名称的Controller类,则Controller匹配成功,但此时仅仅是Controller匹配成功,最终接口能否成功调用还需取决于下一个步骤中的Action匹配。
Controller的匹配主要由接口:IHttpControllerSelector.SelectController方法来处理的,这个是WebApi框架定义的接口,定义如下:
public interface IHttpControllerSelector
{
// Methods
IDictionary<string, HttpControllerDescriptor> GetControllerMapping();
HttpControllerDescriptor SelectController(HttpRequestMessage request);
}
WebApi框架对控制器的匹配进行了默认的实现,类名叫做:DefaultHttpControllerSelector,这个类默认实现了查找Controller的过程,在DefaultHttpControllerSelector内部通过
IHttpControllerTypeResolver接口加载出所有的满足条件的控制器类型,能被加载并查找的控制器类型必须满足以下条件:
1、类必须是实现了IHttpController接口
2、必须是public
3、不能是abstract类
4、类名必须以Controller结尾
最终,从这些列表中找出名称和路由数据中的Controller名同名的Controller类,并创建该类的实例对象。
当然如果我们需要有自己的控制器匹配的逻辑,我们也可以对其进行配置,通过在:/App_Start/WebApiConfig.cs类中进行配置,配置方式如下所示:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// 这里我们配置成使用自己写的匹配控制器的逻辑
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new MyHttpControllerSelectory(GlobalConfiguration.Configuration));
}
}
虽然WebApi框架给我们提供了匹配控制器行为的扩展点,但是微软的默认实现类DefaultHttpControllerSelector基本上可以满足大多数场景了。
四、Action匹配
路由机制找到了将要被调用的Controller类后,接下来就是在当前已经被匹配成功的控制器类下找一个合适的Action方法,并对其调用了,Action的具体匹配流程如下:
1、根据用户调用接口时的请求方式(GET/POST/DELETE/PUT/Head等等)从已经匹配的控制器类中查找是用于该种请求方式的Action方法,通过该轮匹配可能会匹配出多个符合条件的Action方法。
2、如果路由数据字典中包含键为:action的值,那么表示Action的名称必须和该字典中的actionName相一致,也就是说只有Action方法的名称和路由数据字典中的action名匹配的才算再次步骤匹配。(该步骤不一定是必须执行的,取决于被匹配的路由中是否有指定action占位符)
3、最后一步就是action的参数绑定了,action中的各个参数的值要么来源于路由Url模板中定义好的参数在Url中提取到的值,要么来源于QueryString(也就是?后面的参数值),当然这些说的只是.NET中的原生类型(包括:int/double/DateTime/TimeSpan/Guid等等)的绑定。并不包括自定义的复杂类型(如模型类),其实复杂类型的参数值的绑定默认实现方式是从请求报文提中获得的。
Action的选择由接口IHttpActionSelector.SelectAction()方法进行实现,WebApi框架对Action的匹配进行了默认的实现,默认实现类名为:ApiControllerActionSelector,
IHttpActionSelector接口定义如下:
public interface IHttpActionSelector
{
// Methods
ILookup<string, HttpActionDescriptor> GetActionMapping(HttpControllerDescriptor controllerDescriptor);
HttpActionDescriptor SelectAction(HttpControllerContext controllerContext);
}
需要说明的是:能作为Action被执行的方法必须满足以下几点:
1、必须是public修饰的方法
2、未被[NonAction]特性修饰的方法
3、不是从ApiController类中继承过来的方法
4、控制器的构造函数,等等也不会被匹配。
Action的匹配我们也可以实现自定义匹配规则,和上面提到的自定义Controller匹配规则的配置方式类似,如下:
public static void Register(HttpConfiguration config)
{
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionSelector), new MyApiControllerActionSelector()); }
本文主要讲述了WebApi框架如何将来自用户的接口调用请求映射到具体的Controller和Action,并对其进行执行的过程,最容易让人困惑的部分或许还是Action的选择部分,
后续我们将继续讨论关于Action选择部分的具体细节以及参数绑定过程。
WebApi-路由机制的更多相关文章
- C#进阶系列——WebApi 路由机制剖析:你准备好了吗?
前言:从MVC到WebApi,路由机制一直是伴随着这些技术的一个重要组成部分. 它可以很简单:如果你仅仅只需要会用一些简单的路由,如/Home/Index,那么你只需要配置一个默认路由就能简单搞定: ...
- 【C#】 WebApi 路由机制剖析
C#进阶系列——WebApi 路由机制剖析:你准备好了吗? 转自:https://blog.csdn.net/wulex/article/details/71601478 2017年05月11日 10 ...
- C#进阶系列——WebApi 路由机制剖析:你准备好了吗? 转载https://www.cnblogs.com/landeanfen/p/5501490.html
阅读目录 一.MVC和WebApi路由机制比较 1.MVC里面的路由 2.WebApi里面的路由 二.WebApi路由基础 1.默认路由 2.自定义路由 3.路由原理 三.WebApi路由过程 1.根 ...
- WebApi 路由机制剖析
阅读目录 一.MVC和WebApi路由机制比较 1.MVC里面的路由 2.WebApi里面的路由 二.WebApi路由基础 1.默认路由 2.自定义路由 3.路由原理 三.WebApi路由过程 1.根 ...
- WebApi路由机制详解
随着前后端分离的大热,WebApi在项目中的作用也是越来越重要,由于公司的原因我之前一直没有机会参与前后端分离的项目,但WebApi还是要学的呀,因为这东西确实很有用,可单独部署.与前端和App交互都 ...
- MVC和WebApi路由机制比较
1.MVC使用的路由 在MVC中,默认路由机制是通过解析url路径来匹配Action.比如:/User/GetList,这个url就表示匹配User控制器下的GetList方法,这是MVC路由的默认解 ...
- WebApi-1 与MVC路由机制比较
在MVC里面,默认路由机制是通过url路径去匹配对应的action方法 public class RouteConfig { public static void RegisterRoutes(Rou ...
- Web Api 的 路由机制
ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动设备)的 HTTP 服务. ASP.NET Web API 是一种用于在 .NET Framework 上构 ...
- Linux mips64r2 PCI中断路由机制分析
Linux mips64r2 PCI中断路由机制分析 本文主要分析mips64r2 PCI设备中断路由原理和irq号分配实现方法,并尝试回答如下问题: PCI设备驱动中断注册(request_irq) ...
- 走进AngularJs(八) ng的路由机制
在谈路由机制前有必要先提一下现在比较流行的单页面应用,就是所谓的single page APP.为了实现无刷新的视图切换,我们通常会用ajax请求从后台取数据,然后套上HTML模板渲染在页面上,然而a ...
随机推荐
- python scrapy框架爬虫遇到301
1.什么是状态码301 301 Moved Permanently(永久重定向) 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一.如果可能,拥有链接编 ...
- JavaScript(第十三天)【内置对象】
学习要点: 1.Global对象 2.Math对象 ECMA-262对内置对象的定义是:"由ECMAScript实现提供的.不依赖宿主环境的对象,这些对象在ECMAScript程序执行之前就 ...
- [福大软工] W班 软件产品案例分析
作业要求 https://edu.cnblogs.com/campus/fzu/FZUSoftwareEngineering1715W/homework/1300 评分细则 第一部分 调研,评测 (3 ...
- 一起happy--C++小组Alpha版本发布说明
1 功能介绍 该PC端APP,是一个同行者的信息搜索平台,旨在为喜欢游玩,但是身边同学朋友时间冲突,想找人结伴的年轻人提供一个检索平台,让他们尽量能够快速便捷的寻找合适同行者.该APP有登录.注册.主 ...
- Beta版本展示博客
1 团队介绍 团队组成: 齐爽爽(258)个人博客:http://www.cnblogs.com/shuangshuangblog/ 马帅(248)个人博客:http://www.cnblogs.co ...
- python3变量和数据类型
变量和数据类型 知识点 python 关键字 变量的定义与赋值 input() 函数 字符串的格式化 实验步骤 每一种编程语言都有它们自己的语法规则,就像我们所说的外语. 1. 关键字和标识符 ...
- Beta冲刺Day3
项目进展 李明皇 今天解决的进度 完善了程序的运行逻辑(消息提示框等) 明天安排 前后端联动调试 林翔 今天解决的进度 向微信官方申请登录验证session以维护登录态 明天安排 继续完成维护登录态 ...
- JAVA_SE基础——18.方法的递归
方法的递归是指在一个方法的内部调用自身的过程,递归必须要有结束条件,不然就会陷入无限递归的状态,永远无法结束调用,接下来用一个最简单的例子来体现下方法递归,使用递归算法计算自然数之和: public ...
- JAVA_SE基础——4.path的临时配置&Classpath的配置
这次,我来写下关于path的临时配置的心的 我来说个有可能的实例:如果你去到别人的电脑 又想写代码 又不想改乱别人的path配置的话 再说别人愿意你在别人的电脑上瞎配吗? 那该怎么办呢? 那没问题 ...
- 彻底搞懂shell的高级I/O重定向
本文目录: 1.1 文件描述符(file description,fd) 1.2 文件描述符的复制 1.3 重定向顺序很重要:">file 2>&1"和&quo ...