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

前言

前面的几个篇幅对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 selfhost宿主环境中管道、路由
  • ASP.NET Web API webhost宿主环境中管道、路由

ASP.NET Web API SelfHost宿主环境管道

首先我们先来看个示意图,大概的描述了在SelfHost宿主环境中管道形态。

图1

因为在WebHost宿主环境中ASP.NET Web API的管道请求接收以及响应的返回最后都是由ASP.NET来包办的(下一篇中讲解),而在SelfHost宿主环境中就苦逼了,没有那么简单了。

我们按照图1中示意的来讲解,首先在SelfHost宿主环境中的项目启动之后(当然项目要使用Web API框架的),会有一个HttpBinding对象(System.Web.Http.SelfHost.Channels),那这个HttpBinding类型的对象是干嘛的呢?Httpbinding对象对应着一些个BindingElement对象,而这些BindingElement又各自生成对应的管道层监听器,这样就如图1中所示的那样,现在我们看一下如下的示例代码,看看HttpBinding到底对应着哪些BindingElement对象。

示例代码1-1

    public class HttpBinding : Binding, IBindingRuntimePreferences
{
public HttpBinding()
{
this.Initialize();
}
private void Initialize()
{
this._security = new HttpBindingSecurity();
this._httpTransportBindingElement = new HttpTransportBindingElement();
this._httpTransportBindingElement.ManualAddressing = true;
this._httpsTransportBindingElement = new HttpsTransportBindingElement();
this._httpsTransportBindingElement.ManualAddressing = true;
this._httpMessageEncodingBindingElement = new HttpMessageEncodingBindingElement();
}
}

在示例代码1-1中我们可以清楚的看到在HttpBinding对象的构造函数中分别的对几种BindingElement进行了实例化赋值,我们只对其中的HttpTransportBindingElement和HttpMessageEncodingBindingElement进行讲解也就是图1中所示的那样。

HttpTransportBindingElement对象的主要职责就是生成相对应的管道监听器,这里对应的就是IChannelListener<TChannel>泛型类型了,而生成好对应的管道监听器之后,监听器之后会开始监听与之对应的管道层,与HttpTransportBindingElement对象以及监听器对应的也就是TransprotChannel管道层了,它负责请求消息的接收和响应消息的发送。

HttpMessageEncodingBindingElement类型的对象所做操作同HttpTransportBindingElement类型一致,都是先要生成对应的管道监听器,在这里与之对应的就是HttpMessageEncodingChannelListener类型,在监听器生成好之后也会去监听对应的EncodingChannel管道层,而EncodingChannel管道层主要的作用就是将请求信息封装为HttpMessage类型的消息对象,之后由HttpMessage消息对象进入ASP.NET Web API框架的管道系统中。

上面说的是在请求未到达ASP.NET Web API框架的管道系统中的时候在外部的一些处理和操作,下面我们就要说明一下内部,在上篇的《ASP.NET Web API 管道模型》篇幅中有示例代码演示过在SelfHost环境下管道的注册,我们这里看一下在SelfHost环境中Web API框架自身的管道系统里的对象的一些类型。

HttpSelfHostServer消息处理程序(实现类-管道头)System.Web.Http.SelfHost

    public sealed class HttpSelfHostServer : HttpServer
{
public HttpSelfHostServer(HttpSelfHostConfiguration configuration);
public HttpSelfHostServer(HttpSelfHostConfiguration configuration, HttpMessageHandler dispatcher);
public Task CloseAsync();
protected override void Dispose(bool disposing);
public Task OpenAsync();
}

可以看到HttpSelfHostServer类型继承自HttpServer,在上篇中我们也就提到过HttpServer是继承自DelegatingHandler抽象类型的消息处理程序基类,DelegatingHandler与HttpMessageHandler的不同之处就是多了个指向下一个处理程序的引用,当然了作为一个管道系统中第一个消息处理程序必须是要有指向下一个处理程序引用的这么一个标识,这样是合理的。我们再看HttpSelfHostServer类型的构造函数的参数类型。

HttpSelfHostConfiguration类型是继承自HttpConfiguration类型的,在上篇中我们也说过,HttpConfiguration中可以配置管道中的大多数信息,这个大家可以自己去看一下。在重载构造函数中有了第二个构造函数参数,HttpMessageHandler类型的参数,在默认使用HttpSelfHostServer的时候假使不使用这个重载的构造函数,那么在HttpSelfHostServer实例化的之前先实例化之前,其基类HttpServer的构造函数开始执行,所以在看下HttpServer类型的构造函数的时候我们可以看到这里默认设置的HttpMessageHandler类型的参数到底是什么样子的。

public HttpServer() : this(new HttpConfiguration())
{
} public HttpServer(HttpMessageHandler dispatcher) : this(new HttpConfiguration(), dispatcher)
{
} public HttpServer(HttpConfiguration configuration) : this(configuration, new HttpRoutingDispatcher(configuration))
{
} public HttpServer(HttpConfiguration configuration, HttpMessageHandler dispatcher)
{
this._initializationLock = new object();
if (configuration == null)
{
throw System.Web.Http.Error.ArgumentNull("configuration");
}
if (dispatcher == null)
{
throw System.Web.Http.Error.ArgumentNull("dispatcher");
}
this._dispatcher = dispatcher;
this._configuration = configuration;
}

这里大家可以清楚的看到是HttpRoutingDispatcher类型作为管道的最后一个处理程序的类型,对于这个类型以及详细的信息,在下面的路由小节中会有说明。

ASP.NET Web API SelfHost宿主环境路由

对于路由的其他知识这里就不说了,就是简要的提一下在SelfHost中路由、管道的一些细节。

图2

这里要详细说明的就是HttpRoutingDispatcher类型中的SendAsync()方法,看下源码中的实现这样更清楚。

    public class HttpRoutingDispatcher : HttpMessageHandler
{
// Fields
private readonly HttpConfiguration _configuration;
private readonly HttpMessageInvoker _defaultInvoker; // Methods
public HttpRoutingDispatcher(HttpConfiguration configuration)
: this(configuration, new HttpControllerDispatcher(configuration))
{
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
IHttpRouteData routeData;
if (!request.Properties.TryGetValue<IHttpRouteData>(HttpPropertyKeys.HttpRouteDataKey, out routeData))
{
routeData = this._configuration.Routes.GetRouteData(request);
if (routeData == null)
{
return TaskHelpers.FromResult<HttpResponseMessage>(request.CreateErrorResponse(HttpStatusCode.NotFound, Error.Format(SRResources.ResourceNotFound, new object[] { request.RequestUri }), SRResources.NoRouteData));
}
request.Properties.Add(HttpPropertyKeys.HttpRouteDataKey, routeData);
}
RemoveOptionalRoutingParameters(routeData.Values);
HttpMessageInvoker invoker = (routeData.Route.Handler == null) ? this._defaultInvoker : new HttpMessageInvoker(routeData.Route.Handler, false);
return invoker.SendAsync(request, cancellationToken);
}
}

我们先看一下HttpRoutingDispatcher类型中构造函数,可以看到在定义的构造函数后面紧接着又在实例基类的构造函数,并且第二个HttpMessageHandler类型的参数为HttpControllerDispatcher实例的对象,这个我们先记住就行了。

下面我们还是回到HttpRoutingDispatcher类型的SendAsync()方法中,首先我们会看到从HttpRequestMessage对象实例的Properties属性集合中获取路由数据对象。

在SelfHost的环境下这是获取不到的,为啥?因为上面以及之前的篇幅中在管道的处理中没有提到过处理路由并且生成路由数据的。所以这个时候会根据HttpConfiguration中的HttpRouteCollection类型的属性Routes,Routes属性再根据SendAsync()方法的参数类型为HttpRequestMessage的request信息获取路由数据对象IHttpRouteData

在匹配成功获取到路由数据对象(IHttpRouteData)之后便会添加至HttpRequestMessage对象实例(request)的Properties属性集合中。

之前对于路由的了解,最后的执行的Handler都是起初定义在路由对象中的,而在实际情况中,我们注册路由的时候并没有,假使这种情况就在现在发生,可以看到routeData.Route.Hander==null这个是成立的,所以执行的是我们先前说过的在构造函数中的HttpControllerDispatcher类型的实例的SendAsync()方法(实际当中HttpControllerDispatcher类型被HttpMessageInvoker类型所封装)。

而HttpControllerDispatcher类型就跟Web API控制器有关了,这里就不提前说了,后面一定会讲到。

作者:金源

出处:http://www.cnblogs.com/jin-yuan/

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

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

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

    ASP.NET Web API WebHost宿主环境中管道.路由 前言 上篇中说到ASP.NET Web API框架在SelfHost环境中管道.路由的一个形态,本篇就来说明一下在WebHost环境 ...

  2. 使用 OWIN 作为 ASP.NET Web API 的宿主

    使用 OWIN 作为 ASP.NET Web API 的宿主 ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动 设备)的 HTTP 服务. ASP.NET ...

  3. Global Error Handling in ASP.NET Web API 2(webapi2 中的全局异常处理)

    目前,在Web API中没有简单的方法来记录或处理全局异常(webapi1中).一些未处理的异常可以通过exception filters进行处理,但是有许多情况exception filters无法 ...

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

    ASP.NET Web API的消息处理管道可以理解为请求到达Controller之前.Controller返回响应之后的处理机制.之所以需要了解消息处理管道,是因为我们可以借助它来实现对请求和响应的 ...

  5. 如何使用ASP.NET Web API OData在Oracle中使用Entity Framework 6.x Code-First方式开发 OData V4 Service

    环境: Visual Studio 2013 + .Net Framework 4.5.2 1.新建项目 2.安装OData,ODP.NET 安装的包: 下面是部分代码: using System; ...

  6. ASP.NET Web API 管道模型

    ASP.NET Web API 管道模型 前言 ASP.NET Web API是一个独立的框架,也有着自己的一套消息处理管道,不管是在WebHost宿主环境还是在SelfHost宿主环境请求和响应都是 ...

  7. ASP.NET Web API 路由对象介绍

    ASP.NET Web API 路由对象介绍 前言 在ASP.NET.ASP.NET MVC和ASP.NET Web API这些框架中都会发现有路由的身影,它们的原理都差不多,只不过在不同的环境下作了 ...

  8. ASP.NET Web API中的Routing(路由)

    [译]Routing in ASP.NET Web API 单击此处查看原文 本文阐述了ASP.NET Web API是如何将HTTP requests路由到controllers的. 如果你对ASP ...

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

    一.概述 RESTful Web API [Web标准篇]RESTful Web API [设计篇] 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用 二.路由 ...

随机推荐

  1. 操作系统篇-调用门与特权级(CPL、DPL和RPL)

    || 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.前言 在前两篇文章(<操作系统篇-浅谈实模式与保护模式>和<操作系统篇-分段机制与GDT|LDT>)中,我们提到 ...

  2. AutoMapper

    什么是AutoMapper? AutoMapper是一个对象和对象间的映射器.对象与对象的映射是通过转变一种类型的输入对象为一种不同类型的输出对象工作的.让AutoMapper有意思的地方在于它提供了 ...

  3. Objective-C三种定时器CADisplayLink / NSTimer / GCD的使用

    OC中的三种定时器:CADisplayLink.NSTimer.GCD 我们先来看看CADiskplayLink, 点进头文件里面看看, 用注释来说明下 @interface CADisplayLin ...

  4. centos7+mono4+jexus5.6.2安装过程中的遇到的问题

    过程参考: http://www.linuxdot.net/ http://www.jexus.org/ http://www.mono-project.com/docs/getting-starte ...

  5. 一道返回num值的小题目

    题目描述: 实现fizzBuzz函数,参数num与返回值的关系如下: .如果num能同时被3和5整除,返回字符串fizzbuzz .如果num能被3整除,返回字符串fizz .如果num能被5整除,返 ...

  6. HTML块级元素

    前面的话   在HTML5出现之前,人们一般把元素分为块级.内联和内联块元素.本文将详细介绍HTML块级元素 h   标题(Heading)元素有六个不同的级别,<h1>是最高级的,而&l ...

  7. Android 剪贴板详解

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Clipboard 如本文有助于你理解 Android 剪贴板,不妨给我一个 Star.对于码农而言, ...

  8. PHP之Memcache缓存详解

         Mem:memory缩写(内存):内存缓存 1.  断电或者重启服务器内存数据即消失,即临时数据: Memcache默认端口:11211 存入方式:key=>>value    ...

  9. Twproject Gantt开源甘特图功能扩展

    1.Twproject Gantt甘特图介绍 Twproject Gantt 是一款基于 jQuery 开发的甘特图组件,也可以创建其它图表,例如任务树(Task Trees).内置编辑.缩放和 CS ...

  10. 深入.NET平台和C#编程总结大全

    对于初学者的你,等到你把这个看完之后就更清楚地认知.NET和C#编程了,好了废话不多说,开始吧!                                                     ...