ASP.NET Core HTTP 管道中的那些事儿
前言
马上2016年就要过去了,时间可是真快啊。
上次写完 Identity 系列之后,反响还不错,所以本来打算写一个 ASP.NET Core 中间件系列的,但是中间遇到了很多事情。首先是 NPOI 的移植工作,移植过后还有一些Bug需要修复,然后一个事情是一个有关于分布式架构中消息一致性的一个中间件设计开发工作,还有就是博客还要坚持写,最后就是还有好几本书需要读,以及消化学习,所以深深感觉到时间不够用。废话不多说了,进入主题。
大部分中间件都是要依赖于 HTTP 管道和 HttpAbstractions 提供的上下文的,所以有必要先介绍一下 ASP.NET Core 在管道中封装了什么,了解清楚之后有助于更高的进阶学习。你看不懂也没有关系,对这些概念有一个认识就可以了,不需要你精通每一步都具体做了哪些东西,达到会用就是我的目的。因为我觉得随着你以后开发的深入,对这些东西使用多了之后,自然会想了解更多,到那个时候,你就会去看源码了。
IApplicationBuilder
IApplicationBuilder 是应用大家最熟悉它的地方应该就是位于 Startup.cs 文件中的 Configure 方法了吧
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseDeveloperExceptionPage();
app.UseStaticFiles();
app.UseMvc();
}
IApplicationBuilder 就像其名字一样,其实很简单,就是对内做了一个接口封装,对外提供了一个扩展,具体来说就是
对内封装了
IServiceProvider ApplicationServices { get; set; }:应用程序使用的服务,就是ConfigureServices注入的那些。IFeatureCollection ServerFeatures { get; }: 工具箱对象,下面会提到的。IDictionary<string, object> Properties { get; }:横跨各个中间件,在他们之间共享数据。
对外扩展了
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware):注册中间件
还有一个 Build 用来返回管道最终的 HttpContext 状态
RequestDelegate Build();: 最终的 RequestDelegate 形态
没什么复杂的东西,就这几个东西需要了解,下面是一个 IApplicationBuilder 的贴图,看起来应该会更直观。

那 RequestDelegate 又是什么东西呢?
RequestDelegate
RequestDelegate 是一个委托,是以委托形式对 HttpContext 的封装,在 ASP.NET Core 中也是非常重要的一个对象,先看一下定义吧。
namespace Microsoft.AspNetCore.Http
{
public delegate Task RequestDelegate(HttpContext context);
}
为什么说这个对象很重要呢,因为在管道中所有的中间件都是直接或者间接的使用到它来做一些功能,因为它包装这 HttpContext 的嘛,而在Web开发中 HttpContext 的地位又是如此的高,接下来就说说 HttpContext。
HttpContext
HttpContext 应该是做Web开发最熟悉的一个对象了,在这个对象中,封装着Http整个管道中的关键对象信息,这个对象同时伴随着整个管道中传输,也就是会经历整个请求的生命周期,所以这个对象非常重要,也是学习Web开发的一个基础知识。
与传统 .NET Framework 中的 System.Web.HttpContext 不同的是,在 ASP.NET Core 中 HttpContext 是一个抽象类,位于 Microsoft.AspNetCore.Http 命名空间下。它有一个默认的实现叫 DefaultHttpContext 位于 Microsoft.AspNetCore.Http 程序集。
我们知道以前的 System.Web.HttpContext 是怎么创建的吧?
在传统ASP.NET程序中,IIS接收到请求之后,会交给 aspnet_isapi.dll 这个程序集,程序集启动 ASP.NET 运行环境,然后调用 ISAPIRuntime 进行封装,封装之后就是一个 HttpWorkRequest 对象了,然后由 HttpRuntime将其转化为一个HttpContext。
所以在System.Web.HttpContext中,其构造函数为 HttpWorkerRequest
namespace System.Web
{
public sealed class HttpContext : IServiceProvider, IPrincipalContainer
{
public HttpContext(HttpWorkerRequest wr);
}
}
也就是说其实构建HttpContext所有的信息都是来自于 IIS 传递下来的 HttpWorkerRequest。
现在,忘了它吧,是的全部忘掉,这个时候你又要骂微软了,尼玛当年为了面试这个东西不知道背了多少遍。 =_=
没办法,时代要发展要进步,我们也需要不断的学习,那在 ASP.NET Core 中,没有了 IIS ,它的 HttpContext 又是如何生成的呢? 构建 HttpContext 所需的信息又怎么来的呢? 客官不要着急,听我慢慢分解
IFeatureCollection
这里就需要先说一下另外一个比较重要接口了,它就是 IFeatureCollection 接口,这个接口是干嘛的呢? 我们先看一下它的定义:
public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>>
{
bool IsReadOnly { get; }
int Revision { get; }
object this[Type key] { get; set; }
TFeature Get<TFeature>();
void Set<TFeature>(TFeature instance);
}
看到这个接口的定义应该能够明白其功能了,接口继承于IEnumerable<KeyValuePair<Type, object>> 说明接口是一个键值对的集合,我们给接口取个名字吧,叫“工具箱”。
有些同学应该猜出来了,是的,ASP.NET Core中构建 HttpContext 就是所有需要的组件都是来自于 工具箱,那么 工具箱 里面都有什么呢?可以看到工具箱里面有 IHttpRequestFeature, IHttpResponseFeature, ISessionFeature 等等还有很多就不一一列举了,正是由于这一个一个的工具箱里面的工具,最终构建成为了整个 HttpContext 对象。我们来看一下 HttpContext 对象的构造函数:
namespace Microsoft.AspNetCore.Http
{
public class DefaultHttpContext : HttpContext
{
public DefaultHttpContext(IFeatureCollection features)
{
Initialize(features);
}
}
}
没错吧,有同学可能要问了,工具箱里面的这些工具什么时候初始化的呢? 先别急,我们先看看我们熟悉的 Request 和 Response。
HttpRequest
同样在 ASP.NET Core ,HttpRequest 也成为了一个抽象类,它的默认实现叫 DefaultHttpRequest,主要是封装浏览器对服务器的请求的各种数据,包括浏览器请求的网址,查询字符串数据或表单数据等等...

不一一详细介绍了,都是很简单的内容。
HttpResponse
HttpResponse 也成为了一个抽象类,它的默认实现叫 DefaultHttpResponse,主要是是服务器接收到浏览器的请求后,处理返回结果常用的一个对象。

ASP.NET Core 管道
是时候该解释一下上面的 工具箱 初始化的问题了,我想我用一个图来直接说明管道中的请求再合适不过了,下面就是一个 ASP.NET Core 整个服务端构建管道一个流程图:

从图中可以看到,RequestDelegate 携带着 HttpContext 一路经过各种 Server、Hosting 等,最终到达了由 IApplicationBuilder 构建出来的 Application pipeline 这一管道区域,然后再经过各种中间件处理,最终构建出来了我们的 Response,而我们的工具箱 也正是在这个过程中变得 “ 饱满 ” 起来。
有一个需要知道的知识点就是,中间件是怎么样添加或者叫注册到管道中的呢? 又是如何被应用起来的呢?
上面的图可以看到,橙色区域的 Application pipeline 是由 IApplicationBuilder 构建起来的。也就是说我们可以在 IApplicationBuilder 做点什么东西来添加我们的中间件。 是的 IApplicationBuilder 暴露出来了一个 IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); 方法来让我们注册中间件,也就是说位于 Startup.cs 文件中的 Configure 方法。
那么又是怎么样应用起来的呢? IApplicationBuilder 在 Hosting 中有一个 IApplicationBuilderFactory 的对象,Hosting 通过这个Factory 创建之后就会传递到了 HostingApplication 对象中,最后由 IWebHost 对象调用 IServer 对象的Start 同时把 HostingApplication传递进去来最终启动服务端。可以对照上面的图理解一下。
总结
在本篇中,我们知道了 ASP.NET Core Http 管道中的几个对象,他们分别是 IApplicationBuilder , RequestDelegate , HttpContext , HttpRequest , HttpResponse,IFeatureCollection 等,然后也知道了他们之间的关系,接着我们通过一个管道流程图知道了他们的调用关系,也知道了如何向管道中注册中间件。
总体来说的话,本篇内容都比较抽象,写这篇文章也花了我很多的时间,如果你觉得对你有帮助的话,感谢右下角的【推荐】。
本文地址:http://www.cnblogs.com/savorboard/p/aspnetcore-http-pipeline.html
作者博客:Savorboard
欢迎转载,请在明显位置给出出处及链接
ASP.NET Core HTTP 管道中的那些事儿的更多相关文章
- ASP.NET Core真实管道详解[2]:Server是如何完成针对请求的监听、接收与响应的【上】
Server是ASP .NET Core管道的第一个节点,负责完整请求的监听和接收,最终对请求的响应同样也由它完成.Server是我们对所有实现了IServer接口的所有类型以及对应对象的统称,如下面 ...
- 用.Net Core控制台模拟一个ASP.Net Core的管道模型
在我的上几篇文章中降到了asp.net core的管道模型,为了更清楚地理解asp.net core的管道,再网上学习了.Net Core控制台应用程序对其的模拟,以加深映像,同时,供大家学习参考. ...
- asp.net core mvc 管道之中间件
asp.net core mvc 管道之中间件 http请求处理管道通过注册中间件来实现各种功能,松耦合并且很灵活 此文简单介绍asp.net core mvc中间件的注册以及运行过程 通过理解中间件 ...
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...
- 如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容?
原文:如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容? 文章名称: 如何在ASP.NET Core自定义中间件读取Request.Body和 ...
- ASP.NET Core Web API中使用Swagger
本节导航 Swagger介绍 在ASP.NET CORE 中的使用swagger 在软件开发中,管理和测试API是一件重要而富有挑战性的工作.在我之前的文章<研发团队,请管好你的API文档& ...
- ASP.NET Core 2.1 中的 HttpClientFactory (Part 3) 使用Handler实现传出请求中间件
原文:https://www.stevejgordon.co.uk/httpclientfactory-aspnetcore-outgoing-request-middleware-pipeline- ...
- 翻译一篇英文文章,主要是给自己看的——在ASP.NET Core Web Api中如何刷新token
原文地址 :https://www.blinkingcaret.com/2018/05/30/refresh-tokens-in-asp-net-core-web-api/ 先申明,本人英语太菜,每次 ...
- 探索ASP.Net Core 3.0系列二:聊聊ASP.Net Core 3.0 中的Startup.cs
原文:探索ASP.Net Core 3.0系列二:聊聊ASP.Net Core 3.0 中的Startup.cs 前言:.NET Core 3.0 SDK包含比以前版本更多的现成模板. 在本文中,我将 ...
随机推荐
- Entity Framework Core 实现MySQL 的TimeStamp/RowVersion 并发控制
将通用的序列号生成器库 从SQL Server迁移到Mysql 遇到的一个问题,就是TimeStamp/RowVersion并发控制类型在非Microsoft SQL Server数据库中的实现.SQ ...
- Connect() 2016 大会的主题 ---微软大法好
文章首发于微信公众号"dotnet跨平台",欢迎关注,可以扫页面左面的二维码. 今年 Connect 大会的主题是 Big possibilities. Bold technolo ...
- 【Win 10 应用开发】启动远程设备上的应用
这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...
- 认识 Azure
本文为官网摘录总结
- [APUE]UNIX进程的环境(上)
一. 前言 本章将学习:当执行程序时,其main函数是如何被调用的,命令行参数是如何传送给执行程序的,典型的存储器布局是什么样式,如何分配另外的存储空间,进程如何使用环境变量,进程终止的不同方式等.另 ...
- 菜鸟Python学习笔记第二天:关于Python黑客。
2016年1月5日 星期四 天气:还好 一直不知道自己为什么要去学Python,其实Python能做到的Java都可以做到,Python有的有点Java也有,而且Java还是必修课,可是就是不愿意去学 ...
- Entity Framework 手动使用migration里面的up 和down方法。
add-migration -IgnoreChanges 201606100717405_201606100645298_InitialCreate 执行这一句后 ,清空使用map生成的代码,个人不太 ...
- 信息安全-5:RSA算法详解(已编程实现)[原创]
转发注明出处:http://www.cnblogs.com/0zcl/p/6120389.html 背景介绍 1976年以前,所有的加密方法都是同一种模式: (1)甲方选择某一种加密规则,对信息进行加 ...
- [AlwaysOn Availability Groups]健康模型 Part 1——概述
健康模型概述 在成功部署AG之后,跟踪和维护健康状况是很重要的. 1.AG健康模型概述 AG的健康模型是基于策略管理(Policy Based Management PBM)的.如果不熟悉这个特性,可 ...
- μCos-ii学习笔记1_概述
一.μCos-ii _概述 网上关于μCosii的文章多不胜数,本人学习的过程中也参考了很多人的理解和想法,看的是卢有亮老师的<嵌入式实时操作系统-μC/OS原理与实践>(第2版),同时也 ...