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


    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类型在控制器部分解说。



    作者:金源

  • 相关阅读:
    cssmagic/action js
    sublime Text快捷键
    CSS3动画整理
    有个名字叫随便乱记——JS
    读取Excel文件中的单元格的内容和颜色
    在Windows下利用php自带的mail函数发邮件
    装个Redmine真是麻烦啊
    MVC的项目使用html编辑器UEditorMINI
    数锐科技新网站上线
    本来运行的好的Ajax.dll怎么突然不起作用了
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5081499.html
Copyright © 2020-2023  润新知