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. 如何选择PHP框架?

    PHP是世界上最受欢迎的编程语言之—.最近发布的PHP7令这种服务器的编程语言比以前变得更好,更稳定了. PHP被广泛应用于重大的项目.例如Facebook就是使用PHP来维护和创建它们的内部系统的. ...

  2. ExtJS 4.2 组件介绍

    目录 1. 介绍 1.1 说明 1.2 组件分类 1.3 组件名称 1.4 组件结构 2. 组件的创建方式 2.1 Ext.create()创建 2.2 xtype创建 1. 介绍 1.1 说明 Ex ...

  3. AJAX操作数据

    本文使用AJAX访问数据库文件,并显示在网页中.另外还有AJAX对数据库的删除操作,网页不加载,只刷新数据. 随意使用数据库中的一张表: 使用AJAX显示表中内容,首先打入body代码: <h1 ...

  4. MementoPattern(备忘录模式)

    /** * 备忘录模式 * @author TMAC-J * 用于存储bean的状态 */ public class MementoPattern { public class Memento{ pr ...

  5. 树莓派 基于Web的温度计

    前言:家里的树莓派吃灰很久,于是拿出来做个室内温度展示也不错. 板子是model b型. 使用Python开发,web框架是flask,温度传感器是ds18b20 1 硬件连接 ds18b20的vcc ...

  6. [Django]用户权限学习系列之设计自有权限管理系统设计思路

    若在阅读本片文章遇到权限操作问题,请查看本系列的前两章! http://www.cnblogs.com/CQ-LQJ/p/5609690.html和http://www.cnblogs.com/CQ- ...

  7. CSS命名规范——BEM思想(非常赞的规范)

    人们问我最多的问题之一是在CSS类名中“--”和“__”是什么意思?它们的出现是源于BEM和Nicolas Gallagher... BEM的意思就是块(block).元素(element).修饰符( ...

  8. Mono 3.8发布:性能进一步改进,可伸缩性提升

    9月4日,Mono 3.8.0发布了.该版本的运行时带来了一些性能和可伸缩性方面的改进,同时完成了向Windows平台的移植. Mono遵循Gnome和Linux内核的版本编号策略,这意味着3.8是3 ...

  9. Asp.Net 5 新增公告仓库

    一直以来Asp.Net 5 都没有一个比较统一的公告页,对于一个在日夜更新的项目来说,很多人经常会遇到问题但是不知道去哪里寻找帮助,现在Asp.Net 5 项目组新增了一个公告仓库来解决这个问题.  ...

  10. 吸顶大法 -- UWP中的工具栏吸顶的实现方式之一

    如果一个页面中有很长的列表/内容,很多应用都会在用户向下滚动时隐藏页面的头,给用户留出更多的阅读空间,同时提供一个方便的吸顶工具栏,比如淘宝中的店铺页面. 下面是一个比较简单的实现,如果有同学有更好的 ...