ASP.NET WEB API处理流程
前言:大图请看 http://www.asp.net/posters/web-api/ASP.NET-Web-API-Poster.pdf
Web Api Hosting
我们不仅可以通过Web应用程序作为Web api的宿主,也可以使用任意的托管应用,如控制台程序,这个时候我们只需加载Web Api的类库。
- Hosting:当我们使用asp.net应用作为web api的宿主,那么生命周期将开始于HttpControllerHandler,HttpControllerHandler是IHttpControllerHandler接口的实现,它负责创建请求,并把请求带入web api的服务管道。
- SelfHosting:当我们使用自我宿主时。那么服务管道的生命周期将从HttpSelfHostServer 开始,HttpSelfHostServer 是HttpServer 的子类,HttpSelfHostServer 具有监听、接收以及对请求进行相应的能力。
HttpConfiguration
HttpConfiguration在WebApi中比较重要,代表了WebAPi的一个全局配置。如果想要扩展WebApi,一般要对HttpConfiguration进行自定义的配置,修改webapi原有的实现,替换成自己的实现。具体的属性如下表。
表格 1
名称 |
说明 |
获取或设置与此实例关联的依赖关系解析程序。 |
|
获取适用于所有使用此 HttpConfiguration 实例提供的请求的筛选器列表。 |
|
获取此实例的媒体类型格式化程序。 |
|
获取或设置一个值,该值指示是否应在错误消息中包含错误详细信息。 |
|
获取或设置在使用 HttpConfiguration 实例处理请求之前将执行该实例的最终初始化的操作。 |
|
获取当 HttpRequestMessage 在堆栈中向上遍历,且 HttpResponseMessage 在堆栈中向下遍历以进行回应时要调用的 DelegatingHandler 实例的排序列表。 |
|
与参数绑定方式相关的规则的集合。 |
|
获取与此实例关联的属性。 |
|
获取与此 HttpConfiguration 实例关联的 HttpRouteCollection。 |
|
获取与此实例关联的默认服务的容器。 |
|
获取根虚拟路径。 |
HttpControllerHandler
想对于MVC来说MVC的IHandler为MVCHandler,WebAPi的IHander为HttpControllerHandler,它们都会在注册路由的时候被映射,与MVC不同的是,HttpControllerHandler将会被设置成单例。HttpControllerHandler会根据Request来创建出HttpRequestMessage。
HttpRequestMessage、HttpResponseMessage
这两个对象实际上就是对我们熟悉的HttpRequest和HttpResponse的封装,web api里面请求的输入输出都是由这两个对象来完成的,HttpRequestMessage除了包含了HttpRequest的基本信息。HttpRequestMessage具体的属性如下:
表格 2
名称 |
说明 |
获取或设置 HTTP 消息的内容。 |
|
获取 HTTP 请求标头的集合。 |
|
获取或设置 HTTP 请求信息使用的 HTTP 方法。 |
|
获取 HTTP 请求的属性集。 |
|
获取或设置 HTTP 请求的 Uri。 |
|
获取或设置 HTTP 消息版本。 |
HTTP Message Handlers
HTTP Message handlers是进入web api处理管道的第一步,请求进入管道后将会经过一系列的Message handler进行加工处理,我们也可以加入自定义的Message Handler,这些Message handler都是DelegatingHandler 的子类。
这些Message Handler可以是全局的也可以是针对于某个特殊的请求,这些特殊的请求,我们可以在设置路由的时候进行配置。(请看HttpRoutingDispatcher)
Delegating Handler
Delegating Handler是web pai中一个重要的扩展点。Delegating Handler位于Web api处理管道的前端,基本上是每个请求的必经之路。
在图上我也能看到Response的输出也是要进入Delegating Handler。这些自定义的处理可以是请求的监视、请求的筛选、或者是异常处理。
这里的Delegating Handler不仅仅只有一个,我们可以在HttpConfiguration进行配置,加入自定义的Delegating Handler。Delegating Handler的处理将形成一个链路,第一个Delegating Handler处理完后交由下一个Delegating Handler来处理,当没有自定义的Delegating Handler进行处理的时候,web api会调用HttpRoutingDispatcher(实际上HttpRoutingDispatcher也是DelegatingHandler的子类,而且HttpServer也是DelegatingHandler的子类)。DelegatingHandler的代码如下(删掉了写无关紧要的代码)。
public abstract class DelegatingHandler : HttpMessageHandler
{
private HttpMessageHandler innerHandler;//具有一个ttpMessageHandler的属性
protected DelegatingHandler(HttpMessageHandler innerHandler)
{
this.InnerHandler = innerHandler;
} protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null)
throw new ArgumentNullException("request", SR.net_http_handler_norequest);
this.SetOperationStarted();
return this.innerHandler.SendAsync(request, cancellationToken);//直接调用innerHandler的方法
}
} public abstract class HttpMessageHandler : IDisposable
{
protected internal abstract Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
}
HttpRoutingDispatcher
如果自定义的Delegating Handler处理完了,那么请求将会被HttpRoutingDispatcher来处理,顾名思义,“Http路由分发器”,他会判断当前请求的路由数据里面是否包含Handler属性,默认情况下都是空的,因为我们在映射web api的路由时默认没有指定Handler的。如果有,web api会将请求直接交由这个Handler处理,并且返回,而不经过后面的步骤,如Controller激活、模型绑定等等。
如果我们对某个路由映射了指定的Handler,处理完后想要继续执行Controller、Actioin等之后的操作也是可以的,我们只要把一个相互链接好的Handler链映射给这个路由。
具体做法请看:http://www.asp.net/web-api/overview/working-with-http/http-message-handlers
HttpControllerDispatcher
HttpControllerDispatcher所做的事情就是将请求分发给具体的Controller。我们想一下,现在我们能拿就是HttpRequestMessage,通过HttpRequestMessage我们还可以拿到路由数据,在路由数据中我们就能得到Controller的名称。知道一个类的名称,那我们该如何创建它呢?我们首先应该要获取这个类的类型(Type),获取这个类的类型(Type)的工作就由IHttpControllerTypeResolver来做,但是要得到这个类的类型我们就必须知道这个类所在的程序集(Assembly)这个工作就由IAssembliesResolver来做。图中我们可以看到IHttpController返回的类型是HttpControllerDescriptor(实际上就是对于Controller类的描述,相对应的还有HttpActionDescriptor、HttprParameteDescriptor,这和MVC是类似的。拿到HttpControllerDescriptor对象后就应该对Controller进行激活。
IHttpControllerActivator
Controller的激活依赖于IHttpControllerActivator,而IHttpControllerActivator的调用又依赖于IDependencyResolver(依赖注入的方式)。具体体来说IHttpControllerActivator要对Controller激活,首选采用IDependencyResolver方式激活,并且返回IHttpController,如果返回的IHttpController是空,那就采用反射的形式激活。
但是对于IDependencyResolver的默认实现为EmptyResolver,EmptyResolver永远都是返回空。
Select Controller Action
找到了正确的Controller之后,我们就应该去找对应的Action,web api中通过IHttpActionSelector接口返回一个HttpActionDescriptor对象,HttpActionDescriptor和上面的HttpControllerDescriptor类似,是对于Action的描述。截止到这一步,实际上还没有真正的执行Action,而是创建出了HttpActionDescriptor对象。
Authorization Filters
在创建HttpActionDescriptor对象时,各种Filters也会被初始化,首先请求将先进入Authorization Filters进行权限的判断,如果通过,进入下一步,如果不通过直接返回。
Model Binding
请求分为三部分URI、Header、Entity-body。
- URI Binding:对于URI上的参数,web api使用ModelBinderParameterBinding进行处理,ModelBinderParameterBinding的处理跟MVC类似,需要依赖IModelBinder和IValueProvoder。
- Formatter Binding:对于请求体,Web Api会使用FormatterBinding对参数进行绑定。
- HTTP parameter binding:如果我们想对整个请求进行绑定,则需要我们需要有一个自定义的ModelBinder。
Action Filter
当完成了模型绑定的任务之后,就开始进入Action Filter,它会被执行两次,分别是在OnExecuting和OnExecution事件是被调用。
Action Invoker
IHttpActionInvoke的作用就是激活Action,并且返回HttpResponseMessage。激活Action是通过调用HttpActionDescriptor(表示对于action方法的描述)对象中的ExecuteAsync方法。而HttpResponseMessage的返回则由ResultConverter完成。
ResultConverter
IActionResultConverter的接口通过唯一的方法Converter实现。针对返回值的不同,转换的类型也不同。
- HttpResponseMessage:如果Action方法的返回值是HttpResponseMessage则无需转化。
- Void:若果是无返回值,将返回一个空的HttpResponseMessage。
- ValueResultConverter<T>:这种情况下,会通过IContentNegotiator根据请求期望得到的媒体类型,而选择相对应的MediaTypeFormatter进行序列化。
截止到这一步,已经完成了对于HttpResponse对象的创建,接下来HttpResponse就会沿着相反的路程返回给客户端。
p.s.如果错误,请指正,谢谢!
参考:
ASP.NET-Web-API-Poster:http://www.asp.net/posters/web-api/ASP.NET-Web-API-Poster.pdf
asp.net webapi :http://www.asp.net/web-api
Lifecycle of an ASP.NET Web API Message:http://www.dotnetcurry.com/ShowArticle.aspx?ID=888
ASP.NET WEB API处理流程的更多相关文章
- 总体介绍ASP.NET Web API下Controller的激活与释放流程
通过<ASP.NET Web API的Controller是如何被创建的?>我们已经对HttpController激活系统的核心对象有了深刻的了解,这些对象包括用于解析程序集和有效Http ...
- ASP.NET Web API Model-ModelBinder
ASP.NET Web API Model-ModelBinder 前言 本篇中会为大家介绍在ASP.NET Web API中ModelBinder的绑定原理以及涉及到的一些对象模型,还有简单的Mod ...
- ASP.NET Web API 控制器执行过程(一)
ASP.NET Web API 控制器执行过程(一) 前言 前面两篇讲解了控制器的创建过程,只是从框架源码的角度去简单的了解,在控制器创建过后所执行的过程也是尤为重要的,本篇就来简单的说明一下控制器在 ...
- ASP.NET Web API 管道模型
ASP.NET Web API 管道模型 前言 ASP.NET Web API是一个独立的框架,也有着自己的一套消息处理管道,不管是在WebHost宿主环境还是在SelfHost宿主环境请求和响应都是 ...
- ASP.NET Web API 路由对象介绍
ASP.NET Web API 路由对象介绍 前言 在ASP.NET.ASP.NET MVC和ASP.NET Web API这些框架中都会发现有路由的身影,它们的原理都差不多,只不过在不同的环境下作了 ...
- How ASP.NET Web API 2.0 Works?[持续更新中…]
一.概述 RESTful Web API [Web标准篇]RESTful Web API [设计篇] 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用 二.路由 ...
- 跨域资源共享(CORS)在ASP.NET Web API中是如何实现的?
在<通过扩展让ASP.NET Web API支持W3C的CORS规范>中,我们通过自定义的HttpMessageHandler自行为ASP.NET Web API实现了针对CORS的支持, ...
- 《ASP.NET Web API 2框架揭秘》样章(PDF版本)
<ASP.NET Web API 2框架揭秘>(详情请见<新作<ASP.NET Web API 2框架揭秘>正式出版>)以实例演示的方式介绍了很多与ASP.NET ...
- 新作《ASP.NET Web API 2框架揭秘》正式出版
我觉得大部分人都是“眼球动物“,他们关注的往往都是目光所及的东西.对于很多软件从业者来说,他们对看得见(具有UI界面)的应用抱有极大的热忱,但是对背后支撑整个应用的服务却显得较为冷漠.如果我们将整个“ ...
随机推荐
- 2018 ACM-ICPC 青岛网络赛
最近打比赛不知道为什么总是怀疑自己 写完之后不敢交,一定跟学长说一遍自己的思路 然后发现"哦原来我是对的" 然后就A掉了…… 所以还是要有自信 Problem A 最大值直接输出m ...
- 51nod 1201 (dp)
整数划分 将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} {1,5} {2,4} {1,2,3},共4种.由于数据较大,输出Mod 10^9 + 7的结果即可. In ...
- Codeforces Round #274 (Div. 2) Riding in a Lift(DP 前缀和)
Riding in a Lift time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- 【分类讨论】Codeforces Round #407 (Div. 2) D. Weird journey
考虑这个二元组中有一者是自环,则必然合法. 考虑这两条边都不是自环,如果它们不相邻,则不合法,否则合法. 坑的情况是,如果它是一张完整的图+一些离散的点,则会有解,不要因为图不连通,就误判成无解. # ...
- HDU 5631 Rikka with Graph 暴力 并查集
Rikka with Graph 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5631 Description As we know, Rikka ...
- 基于tiny4412的Linux内核移植 -- PWM子系统学习(八)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- 【Tomcat】Tomcat闪退的问题解决/Tomcat修改端口号无效
一. Tomcat闪退的问题解决 1.首先 确定JDK的环境变量配置正确 2.下载纯净的新的Tomcat 3.在bin\startup.bat文件中的第一行前面加入: SET JAVA_HOME = ...
- 用javac编译整个j2ee项目
转自:http://www.blogjava.net/zhyiwww/archive/2011/10/13/361145.html 我们做项目,可能会使用ant做系统集成和部署.其实ant在编译项目时 ...
- Boost::Lexical_cast 的使用
.C++代码 #include <boost/lexical_cast.hpp> #include <iostream> int main() { using boost::l ...
- Mysql - 登录错误
来源: 问题的引出: 我 在CentOS上装完mysql后,用navicat链接的时候,抛出MySql - SQL Error (1130): Host IP is not allowed to co ...