一、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-路由机制的更多相关文章

  1. C#进阶系列——WebApi 路由机制剖析:你准备好了吗?

    前言:从MVC到WebApi,路由机制一直是伴随着这些技术的一个重要组成部分. 它可以很简单:如果你仅仅只需要会用一些简单的路由,如/Home/Index,那么你只需要配置一个默认路由就能简单搞定: ...

  2. 【C#】 WebApi 路由机制剖析

    C#进阶系列——WebApi 路由机制剖析:你准备好了吗? 转自:https://blog.csdn.net/wulex/article/details/71601478 2017年05月11日 10 ...

  3. C#进阶系列——WebApi 路由机制剖析:你准备好了吗? 转载https://www.cnblogs.com/landeanfen/p/5501490.html

    阅读目录 一.MVC和WebApi路由机制比较 1.MVC里面的路由 2.WebApi里面的路由 二.WebApi路由基础 1.默认路由 2.自定义路由 3.路由原理 三.WebApi路由过程 1.根 ...

  4. WebApi 路由机制剖析

    阅读目录 一.MVC和WebApi路由机制比较 1.MVC里面的路由 2.WebApi里面的路由 二.WebApi路由基础 1.默认路由 2.自定义路由 3.路由原理 三.WebApi路由过程 1.根 ...

  5. WebApi路由机制详解

    随着前后端分离的大热,WebApi在项目中的作用也是越来越重要,由于公司的原因我之前一直没有机会参与前后端分离的项目,但WebApi还是要学的呀,因为这东西确实很有用,可单独部署.与前端和App交互都 ...

  6. MVC和WebApi路由机制比较

    1.MVC使用的路由 在MVC中,默认路由机制是通过解析url路径来匹配Action.比如:/User/GetList,这个url就表示匹配User控制器下的GetList方法,这是MVC路由的默认解 ...

  7. WebApi-1 与MVC路由机制比较

    在MVC里面,默认路由机制是通过url路径去匹配对应的action方法 public class RouteConfig { public static void RegisterRoutes(Rou ...

  8. Web Api 的 路由机制

    ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动设备)的 HTTP 服务. ASP.NET Web API 是一种用于在 .NET Framework 上构 ...

  9. Linux mips64r2 PCI中断路由机制分析

    Linux mips64r2 PCI中断路由机制分析 本文主要分析mips64r2 PCI设备中断路由原理和irq号分配实现方法,并尝试回答如下问题: PCI设备驱动中断注册(request_irq) ...

  10. 走进AngularJs(八) ng的路由机制

    在谈路由机制前有必要先提一下现在比较流行的单页面应用,就是所谓的single page APP.为了实现无刷新的视图切换,我们通常会用ajax请求从后台取数据,然后套上HTML模板渲染在页面上,然而a ...

随机推荐

  1. 【分布式系列之dubbo】dubbo管理工具dubbo-admin安装使用

    一.安装完成后界面显示 二.安装 1.下载dubbo-admin安装包 2.修改WEB-INF下的dubbo.properties文件内容 dubbo.registry.address=zookeep ...

  2. C语言第二周作业----分支结构

    一.PTA实验作业 题目1.7-1计算分段函数 本题目要求计算下列分段函数f(x)的值: 注:可在头文件中包含math.h,并调用sqrt函数求平方根,调用pow函数求幂. 1.实验代码 int ma ...

  3. 课后练习:C语言实现Linux命令——od

    课后练习:C语言实现Linux命令--od --------CONTENTS-------- 题目详情与分析 设计思路 遇到的问题及解决 待实现的设想与思考 学习反思与感悟 附1:myod.c「1.0 ...

  4. 20162302 实验一《Java开发环境的熟悉》实验报告

    实 验 报 告 课程:程序设计与数据结构 姓名:杨京典 班级:1623 学号:20162302 实验名称:Java开发环境的熟悉 实验器材:装有Ubuntu的联想拯救者80RQ 实验目的与要求:1.使 ...

  5. Beta冲刺Day7

    项目进展 李明皇 今天解决的进度 部分数据传递和使用逻辑测试 林翔 今天解决的进度 服务器端查看个人发布的action,修改已发布消息状态的action,仍在尝试使用第三方云存储功能保存图片 孙敏铭 ...

  6. 去掉xcode编译warning:ld: warning: directory not found for option '-L

    选择工程, 编译的 (targets) 选择 Build Settings 菜单 查找 Library Search Paths 和 Framework Search Paths, 删掉编译报warn ...

  7. 201421123042 《Java程序设计》第2周学习总结

    1. 本周学习总结 以几个关键词描述本周的学习内容.并将关键词之间的联系描述或绘制出来. 原则:少而精,自己写.即使不超过5行也可,但请一定不要简单的复制粘贴. 引用类型 引用类型是指向一个对象,感觉 ...

  8. react基础篇入门组件

    讲述一下React: 1.声明式设计-React采用声明范式,可以轻松描述应用 2.高效-React通过DOM模型,最大限度的减少dom的交互 3.灵活-React可以与已知的库或框架很好的配合 4. ...

  9. OpenShift实战(二):OpenShift节点扩容

    1.新增节点信息 增加节点如下,请将xxx改为自己的域名 node6.xxx.net Node 192.168.8.90 8G 20G/60G 4C node7.xxx.net Node 192.16 ...

  10. ajax中设置contentType: “application/json”的作用

    最近在做项目交互的时候,刚开始向后台传递数据返回415,后来百度添加了 contentType:"application/json"之后返回400,然后把传输的数据格式改为json ...