寄宿的作用是开启一个进程为Web API提供一个运行环境以解决持续监听、请求监听和响应回复,即将接收到的请求转换成HttpRequestMessage对象传入管道,并将管道生成并经过处理后的HttpResponseMessage回复给客户端。寄宿模式分两种,即Web Host模式和Self Host模式,不同模式下采用的机制不一样,我们先来看看Web Host模式下的消息处理管道。
由前几篇可知,在Web Host模式下,是开启一个ASP.NET Web应用作为Web API的宿主,它借助ASP.NET自身的管道结合IIS解决持续监听、请求接收和响应回复,虽然ASP.NET Web API有自己的路由系统,而且在消息处理管道末端的处理器HttpRoutingDispatcher也具有WebAPI自身的路由解析功能,但采用的还是ASP.NET的路由解析功能,其是利用ASP.NET管道中名称为UrlRoutingModule的ASP.NET的HttpModule来完成,通过注册HttpAppliction的PostResolveRequestCache事件来对请求进行拦截,在其事件处理程序中,借助注册的路由对请求URL进行解析得到路由变量并创建RouteData对象,再从匹配的Route对象中获取对应HttpHandler,而在Web Host模式下往Web API路由表中注册一个HttpRoute对象时候,自动会在ASP.NET路由系统的路由表中注册一个HttpWebRoute类型的Route对象,而HttpWebRoute的RouteHandler固定默认指定为HttpControllerRouteHandler,其GetHandler方法创建并返回 返回一个名为HttpControllerHandler的HttpHandler,GetHandler方法的参数是封装了请求上下文和解析出来的路由数据的RequestContext对象,回l顾下ASP.NET 路由那篇的代码,如下图:
那为啥是这个HttpControllerRouteHandler和HttpControllerHandler呢,回顾下Web Host模式下的路由那篇的代码,如下图 :
以及
而这个HttpControllerHandler会将请求接入到消息处理管道,ASP.NET路由系统就是通过其把ASP.NET管道与ASP.NET Web API消息处理管道进行连通,在其构造函数中,指定了解析的路由数据RouteData,以及GlobalConfiguration提供的默认指定的消息处理管道第一个处理器HttpServer,再看如下代码片段:
以及GlobalConfiguration的代码段:
而HttpControllerHandler的处理方法ProcessRequestAsync起到核心作用,主要有以下几点
- 创建HttpRequestMessage对象
- 把路由数据存放到HttpRequestMessage对象的属性字典中
- 执行HttpServer的SendAsync方法,启动消息处理管道
进入消息处理管道后第一个处理器是HttpServer,我们再回过头看下GlobalConfiguration的创建HttpServer的代码,
而在HttpServer调用SendAync方法时候,会先根据HttpConfiguration里的所有自定义处理器集合以及消息管道的最后一个消息处理器HttpRoutingDispatcher通过InnerHandler属性创建好链式的消息处理管道,如下图
然后,调用以下方法启动管道链式处理:
最后,请求到达了管道中的最后一个消息处理器HttpRoutingDispatcher,由上篇已经说明,其主要有两个作用:
- 路由:如果当前请求中不存在路由数据,就会直接解析进而生成封装路由数据的HttpRouteData
- 消息分发:将请求直接分发给在创建时候指定的HttpControllerDispatcher进一步处理
显然,在前边的HttpControllerHandler的处理方法里已经将路由数据存放到了HttpRequestMessage的属性字典中,所以,这里只需要从请求中获取路由数据,而不需要去直接解析,而HttpControllerDispatcher(也是继承自HttpMessageHandler)是在HttpRoutingDispatcher的构造函数中默认指定的,后续的HttpController激活、Action的执行等操作都是它来执行。