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