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

作者:金源

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

本文版权归作者和CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面

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

时间: 2024-08-01 06:32:44

ASP.NET Web API WebHost宿主环境中管道、路由的相关文章

ASP.NET Web API实践系列05,消息处理管道

ASP.NET Web API的消息处理管道可以理解为请求到达Controller之前.Controller返回响应之后的处理机制.之所以需要了解消息处理管道,是因为我们可以借助它来实现对请求和响应的自定义处理.所有的请求被封装到HttpRequestMessage这个类中,所有的响应被封装到HttpResponseMessage这个类中. 既然消息处理管道是可扩展的,那么,ASP.NET Web API一定为我们准备了便于扩展的接口或抽象类,它就是HttpMessageHandler抽象类.

ASP.NET Web API 路由对象介绍

ASP.NET Web API 路由对象介绍 前言 在ASP.NET.ASP.NET MVC和ASP.NET Web API这些框架中都会发现有路由的身影,它们的原理都差不多,只不过在不同的环境下作了一些微小的修改,这也是根据每个框架的特性来制定的,今天我们就来看一看路由的结构,虽然我在MVC系列里写过路由的篇幅不过在这里是Web API 路由对象介绍. ASP.NET Web API路由.管道 ASP.NET Web API 开篇介绍示例 ASP.NET Web API 路由对象介绍 ASP.

ASP.NET Web API 管道模型

ASP.NET Web API 管道模型 前言 ASP.NET Web API是一个独立的框架,也有着自己的一套消息处理管道,不管是在WebHost宿主环境还是在SelfHost宿主环境请求和响应都是从消息管道经过的,这是必经之地,本篇就为大家简单的介绍一下ASP.NET Web API框架中的管道对象模型. ASP.NET Web API路由.管道 ASP.NET Web API 开篇介绍示例 ASP.NET Web API 路由对象介绍 ASP.NET Web API 管道模型 ASP.NE

ASP.NET Web API中的依赖注入

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 什么是依赖注入 依赖,就是一个对象需要的另一个对象,比如说,这是我们通常定义的一个用来处理数据访问的存储,让我们用一个例子来解释,首先,定义一个领域模型如下: namespace Pattern.DI.MVC.Models{ public cl

How ASP.NET Web API 2.0 Works?[持续更新中…]

一.概述 RESTful Web API [Web标准篇]RESTful Web API [设计篇] 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用 二.路由 ASP.NET的路由系统:URL与物理文件的分离 ASP.NET的路由系统:路由映射 ASP.NET的路由系统:根据路由规则生成URL ASP.NET Web API路由系统的几个核心类型 Web Host下的URL路由 三.消息处理管道 ASP.NET Web API标准的"管道式"设计

ASP.NET Web API 开篇示例介绍

ASP.NET Web API 开篇示例介绍 ASP.NET Web API 对于我这个初学者来说ASP.NET Web API这个框架很陌生又熟悉着. 陌生的是ASP.NET Web API是一个全新的框架,对于这个框架在一个项目中起到的作用我暂且还不是很清楚这里也就不妄下结论了,说实话不是我不想而是我无能为力,只能自己去摸索试着去了解它. 熟悉的是ASP.NET Web API跟ASP.NET MVC的框架结构一开始看起来有一些相似的地方. 话就不多说了,大家就和我一起来学习ASP.NET

ASP.NET Web API的安全管道

本篇体验ASP.NET Web API的安全管道.这里的安全管道是指在请求和响应过程中所经历的各个组件或进程,比如有IIS,HttpModule,OWIN,WebAPI,等等.在这个管道中大致分两个阶段,一个是验证阶段,另一个是授权阶段. 在ASP.NET Web API v1版本的时候,安全管道大致是这样的: → Authentication,请求来到IIS中的HttpModule→ Authenticatin, 请求来到API的HttpMessageHandler→ Authorizatio

Asp.net MVC 与 Asp.net Web API 区别

Asp.Net Web API VS Asp.Net MVC 1.Asp.net MVC 是用来创建返回视图(Views)与数据的Web应用,而Asp.net Web API是一种简单轻松地成熟的HTTP服务,它只返回数据,不返回视图(Views). 2.Asp.net Web API可以通过.Net Framework来帮助我们构建REST-ful服务,而且他支持内容协商(根据客户端能接受的格式要求,返回相应的JSON,XML,ATOM),同时Asp.net Web API支持自我宿主(sel

既生瑜何生亮?ASP.NET MVC VS ASP.NET Web API

Asp.net MVC 与 Asp.net Web API 区别 在我们开发一些web应用时,我们一样可以在MVC Framework 中使用JsonResult 来返回JSON数据,同样也可以处理一下简单的AJAX请求,那么为何微软又推出Web API这么个东西呢?接下来我们来比较一下.二者(Asp.net MVC 与 Asp.net Web Api)何时用? Asp.Net Web API VS Asp.Net MVC 1.Asp.net MVC 是用来创建返回视图(Views)与数据的We