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

时间:2022-11-07 21:37:16

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

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

因为在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

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

这里要详细说明的就是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&period;NET Web API WebHost宿主环境中管道、路由

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

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

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

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

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

  4. ASP&period;NET Web API实践系列05&comma;消息处理管道

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

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

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

  6. ASP&period;NET Web API 管道模型

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

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

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

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

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

  9. How ASP&period;NET Web API 2&period;0 Works&quest;&lbrack;持续更新中…&rsqb;

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

随机推荐

  1. C&num; Cache 设定缓存过期时间方法 绝对过期时间 和 相对过期时间&lpar;即&colon;访问激活后不过期&rpar;

    摘自: http://www.cnblogs.com/zj1111184556/p/3493840.html 1. 设定绝对过期时间 /// <summary> /// 设定绝对的过期时间 ...

  2. UITabBarController使用总结

    刚看了几天教程就开始跟着开发了,以前也没学过C,太痛苦了~只能看看大神的博客,自己再总结学习一下了. 1.首先新建一个TabBarViewController继承于UITabBarController ...

  3. liMarquee演示12种不同的无缝滚动效果

    很实用的一款liMarquee演示12种不同的无缝滚动效果 在线预览 下载地址 实例代码 <!DOCTYPE html> <html lang="zh-CN"&g ...

  4. ubuntu 12&period;04 设置代理

    一. Ubuntu 12.04 apt-get 代理设置 由于公司通过代理上网,firefox的代理设置很容易就搞定了,但是通过apt-get安装软件还是不行,于是,查阅了很多资料,最多的方法就是网上 ...

  5. main函数之后的调用

    main函数代表进程的主线程.程序开始执行时,系统为程序创建一个进程,main函数其实并不是首先被调用的函数,而是操作系统调用了C/C++运行期启动函数,该函数负责对C/C++ 运行期库进行初始化.它 ...

  6. netcore编程之后面对不习惯的xshell黑屏部署,是时候使用jenkins自动化发布工具了

     在很久之前net还只能在windows上部署的时候,或许很多创业公司的朋友发布项目还都是人肉部署,反正windows都是可视化的界面,拖拖拉拉,开开关关还不 是特别麻烦...现如今你的项目需要在li ...

  7. &lbrack;UnityShader基础&rsqb;07&period;MaterialPropertyDrawer

    参考链接: https://blog.csdn.net/e295166319/article/details/60141677 https://docs.unity3d.com/ScriptRefer ...

  8. 云计算概述及Centos7下安装kvm虚拟机

    云计算(cloud computing)是基于互联网的相关服务的增加.使用和交付模式,通常涉及通过互联网来提供动态易扩展且经常是虚拟化的资源 云计算到底是什么? 按定义:云计算指的是一种使用模式,是基 ...

  9. MPC&amp&semi;MAGIC

    MPC: Popularity-based Caching Strategy for Content Centric Networks MPC: most popular content MPC主要思 ...

  10. 前端 html span标签

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...