您的位置:首页 > 编程语言 > ASP

ASP.NET Web API WebHost宿主环境中管道、路由

2015-12-28 08:56 666 查看

ASP.NET Web API WebHost宿主环境中管道、路由

前言

上篇中说到ASP.NET Web API框架在SelfHost环境中管道、路由的一个形态,本篇就来说明一下在WebHost环境中ASP.NET Web API框架中的管道、路由又是哪一种形态。

ASP.NET Web API路由、管道

ASP.NET Web API 开篇介绍演示样例
ASP.NET Web API 路由对象介绍
ASP.NET Web API 管道模型
ASP.NET Web API selfhost宿主环境中管道、路由
ASP.NET Web API webhost宿主环境中管道、路由

ASP.NET Web API webhost宿主环境中管道、路由

以下将会主要解说路由的注冊运行过程(WebHost环境)。对于管道不会去刻意的说明,都会包括在路由的解说中。拆开来说明效果不太好。

HttpRoute->HostedHttpRoute->HttpWebRoute->Route

想要清楚的了解路由的运行过程以及管道的形态。就必须对路由对象熟知。然而在前面的《ASP.NET Web API 路由对象介绍》篇幅中仅仅是分别的对各个环境下的路由对象类型进行了说明。并没有说明转变的过程。

如今就来解说路由对象的“转变”过程。

演示样例代码1-1

protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
"DefaultAPI", "api/{controller}/{id}", new { controller="product",id = RouteParameter.Optional });
}


演示样例代码1-1中是在WebHost环境下进行的路由注冊,依据MapHttpRoute()方法我们转定义过去应该是一个HttpRouteCollection类型的扩展方法类型HttpRouteCollectionExtensions,既然是HttpRouteCollectionExtensions类型里的实现那我们就过去看看究竟啥情况。

演示样例代码1-2

public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, HttpMessageHandler handler)
{
if (routes == null)
{
throw System.Web.Http.Error.ArgumentNull("routes");
}
HttpRouteValueDictionary dictionary = new HttpRouteValueDictionary(defaults);
HttpRouteValueDictionary dictionary2 = new HttpRouteValueDictionary(constraints);
IDictionary<string, object> dataTokens = null;
HttpMessageHandler handler2 = handler;
IHttpRoute route = routes.CreateRoute(routeTemplate, dictionary, dictionary2, dataTokens, handler2);
routes.Add(name, route);
return route;
}


我们能够看到返回类型是IHttpRoute,生成则是由HttpRouteCollection类型的实例调用当中的CreateRoute()方法来实现,这里有的朋友要问了,这不是SelfHost中的路由注冊实现方式吗?回答是对的。仅仅只是在WebHost中利用多态来实现返回成其它的类型。接着往下看。

既然都看到了在这里发生的变化。那说明是有继承了HttpRouteCollection类型的这么一个类型然后创建的路由对象。这样一理就清晰多了,在SelfHost环境中HttpRouteCollection类型是存在于HttpConfiguration类型的对象中,并不单独使用。而在WebHost中也是。

这个时候我们再回过头来看一下代码1-1中的GlobalConfiguration类型中的定义。

演示样例代码1-3

private static Lazy<HttpConfiguration> _configuration = new Lazy<HttpConfiguration>(delegate {
HttpConfiguration configuration = new HttpConfiguration(new HostedHttpRouteCollection(RouteTable.Routes));
configuration.Services.Replace(typeof(IAssembliesResolver), new WebHostAssembliesResolver());
configuration.Services.Replace(typeof(IHttpControllerTypeResolver), new WebHostHttpControllerTypeResolver());
configuration.Services.Replace(typeof(IHostBufferPolicySelector), new WebHostBufferPolicySelector());
return configuration;
});
public static HttpConfiguration Configuration
{
get
{
return _configuration.Value;
}
}


从代码1-3中我们能够看到_configuration静态变量使用了延迟载入,啥意思呢就是以下的那个HttpConfiguration类型的Configuration属性假设使用了才会去实例化,跑偏了这不是重点。

重点是在实例化静态变量_configuration中能够清楚的看到使用了HostedHttpRouteCollection类型的路由集合类型对象作为构造函数參数。

能够自行的去看一下HostedHttpRouteCollection的内部结构。

如今再回到创建路由的那会,也就是代码1-1和代码1-2中所看到的的那样,实际也就是HostedHttpRouteCollection类型在创建路由对象,依照老规矩直接看实现代码。

演示样例代码1-4

public override IHttpRoute CreateRoute(string uriTemplate, IDictionary<string, object> defaults, IDictionary<string, object> constraints, IDictionary<string, object> dataTokens, HttpMessageHandler handler)
{
return new HostedHttpRoute(uriTemplate, defaults, constraints, dataTokens, handler);
}


从代码1-4中能够清楚的看到是返回的是HostedHttpRoute路由对象,我们能够看一下构造函数,仅仅有这样才干知道“转变”的过程。

public HostedHttpRoute(string uriTemplate, IDictionary<string, object> defaults, IDictionary<string, object> constraints, IDictionary<string, object> dataTokens, HttpMessageHandler handler)
{
RouteValueDictionary dictionary = (defaults != null) ? new RouteValueDictionary(defaults) : null;
RouteValueDictionary dictionary2 = (constraints != null) ? new RouteValueDictionary(constraints) : null;
RouteValueDictionary dictionary3 = (dataTokens != null) ? new RouteValueDictionary(dataTokens) : null;
this.OriginalRoute = new HttpWebRoute(uriTemplate, dictionary, dictionary2, dictionary3, HttpControllerRouteHandler.Instance, this);
this.Handler = handler;
}


在代码1-4中我们仅仅须要关注OriginalRoute属性的赋值,OriginalRoute属性是HostedHttpRoute类型里的一个属性,是用来设置对Route对象的引用,演示样例代码1-4中也就是HttpWebRoute类型的对象,对于HttpWebRoute对象的构造函数这里就不例举了。这个时候能够看到是将HttpControllerRouteHandler类型的对象作为Route(HttpWebRoute)对象的RouteHandler(路由处理程序)。

大家都知道ASP.NET Web API框架在WebHost环境中是依赖于ASP.NET的,实则也是通过IHttpModule来进行前期的消息拦截,以下我们看一下在HttpModule中的代码(我想应该是这种,假设有误请指点。



演示样例代码1-5

public class WebAPIHttpModule:IHttpModule
{

public void Dispose()
{
throw new NotImplementedException();
}

public void Init(HttpApplication context)
{
context.PostResolveRequestCache += context_PostResolveRequestCache;
}

void context_PostResolveRequestCache(object sender, EventArgs e)
{
HttpApplication context = sender as HttpApplication;
HttpContextWrapper contextWrapper = new HttpContextWrapper(context.Context);
RouteData routeData = RouteTable.Routes.GetRouteData(contextWrapper);
RequestContext requestContext=new RequestContext(contextWrapper,routeData);
IHttpHandler httpHandler = routeData.RouteHandler.GetHttpHandler(requestContext);
IHttpAsyncHandler httpAsyncHandler = httpHandler as IHttpAsyncHandler;
httpAsyncHandler.BeginProcessRequest(context.Context, null, null);
}
}


在代码1-5中我们能够看到首先是获取了RouteData对象实例,以此获取RouteHandler,然后依据RequestContext获取IHttpHandler,再转换为IHttpAsyncHandler类型的实例。然后调用其BeginProcessRequest()方法来运行操作。

上面这段话描写叙述的是上述代码的运行过程,有的朋友可能会疑问了,怎么就获取RouteData了?

这里我给大家解释一下,在我们的代码1-2中,有这种代码:

IHttpRoute route = routes.CreateRoute(routeTemplate, dictionary, dictionary2, dataTokens, handler2);
routes.Add(name, route);


首先我们看第一句,这里的route上面说过了是HostedHttpRoute对象,这里毫无疑问直接过,然后我们再看第二句,这里的routes是HostedHttpRouteCollection对象不假,可是这个Add()方法加入的方向不是HostedHttpRouteCollection,而是由我们一開始在GlobalConfiguration类型中说过的RouteTable.Routes,当前环境是什么?ASP.NET框架环境对吧!毫无疑问这个Add()方法把上面所说的route(HostedHttpRoute对象)加入到了当前环境的RouteTable.Routes中。有的朋友会问了类型不正确。确实是不正确的在加入的时候route(HostedHttpRoute对象)会转换成HttpWebRoute对象,HttpWebRoute对象继承自Route,能够看前面的篇幅,想必讲到这里大家应该明确了。这里我就不多说了。

我们接着回到代码1-5中,在获取了RouteData之后通过RouteHandler的GetHttphandler()方法获取IHttpHandler实例,在RouteData中的这个RouteHandler毫无疑问就是HttpControllerRouteHandler类型。

我们来看下HttpControllerRouteHandler类型中的GetHttphandler()方法:

protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new HttpControllerHandler(requestContext.RouteData);
}


能够看到是由HttpControllerHandler这个对象类型来运行最后的操作,那我们就来看一下这个类型的定义:

public class HttpControllerHandler : IHttpAsyncHandler, IHttpHandler


如今大家明确为什么要转成IHttpAsyncHandler了吧,由于假设调用了实现了IHttpHandler接口的函数是会报出异常的,由于在HttpControllerHandler类型中并没有实现IHttpHandler接口仅仅是一个空壳,然后我们再看一下HttpControllerHandler类型的静态构造函数:

图1



这个_server是Lazy<HttpMessageInvoker>类型。在BeginProcessRequest()方法中会运行SendAsync()以此进入ASP.NET Web API的管道。

以下我们看一下总体的一个示意图,

图2



最后对于HttpControllerDispatcher类型在控制器部分解说。

作者:金源

出处:http://blog.csdn.net/jinyuan0829

本文版权归作者和CSDN共同拥有,欢迎转载,但未经作者允许必须保留此段声明。且在文章页面
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: