ASP.NET Core Middleware

中间件(Middleware)是ASP.NET Core中的一个重要特性。所谓中间件就是嵌入到应用管道中用于处理请求和响应的一段代码。ASP.NET Core Middleware可以分为两种类型:

  • Conventional Middleware

  • IMiddleware

Conventional Middleware

这种中间件没有实现特定的接口或者继承特定类,它更像是Duck Typing (你走起路来像个鸭子, 叫起来像个鸭子, 那么你就是个鸭子)。有两种表现形式:

匿名方法

这种方式又称为内联中间件(in-line middleware),可以使用Run, Map, Use,MapWhen等扩展方法来实现。如:

640?wx_fmt=png

IApplicationBuilder的扩展方法:RunMapMapWhen
Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware),最终都会调用IApplicationBuilder接口中的Use(Func<RequestDelegate, RequestDelegate> middleware)方法来实现向请求处理管道中注入中间件,后面会对源码做分析。

自定义中间件类

这种形式利于代码的复用,如:

640?wx_fmt=png

将自定义中间件配置到请求处理管道中

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{app.UseXfhMiddleware();
}

IMiddleware

IMiddleware提供了强类型约束的中间件,其默认实现是MiddlewareFactory,接口定义如下:

public interface IMiddleware
{Task InvokeAsync(HttpContext context, RequestDelegate next);
}

IMiddlewareFactory用于创建IMiddleware实例及对实例进行回收,接口定义:

640?wx_fmt=png

将中间件注入到请求处理管道:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{app.UseMyMiddleware();
}

 

使用IMiddleware类型的中间件需要在容器中进行注册,否则抛异常,具体原因下面分析:

 

640?wx_fmt=png

 将中间件注入到容器中:

640?wx_fmt=png

一段警告

下面贴一段微软文档中的警告,大意是不要试图去改变已发往客户端的响应内容,否则可能会引发异常。实在是太懒了,不想翻译就把原文贴出来了:

Warning

Don't call next.Invoke after the response has been sent to the client. Changes to HttpResponse after the response has started throw an exception. For example, changes such as setting headers and a status code throw an exception. Writing to the response body after calling next:

  • May cause a protocol violation. For example, writing more than the stated Content-Length.

  • May corrupt the body format. For example, writing an HTML footer to a CSS file.

HasStarted is a useful hint to indicate if headers have been sent or the body has been written to.


UseMiddleware

前面将自定义中间件注入到请求处理管道时用到了UseMiddleware方法,从方法签名中可以看到UserMiddleware可以接受多个参数:

640?wx_fmt=png

接下来我们看下UserMiddleware方法的具体实现,由于该方法代码量较大,所以这里只看其中的关键部分,方法整体流程如下:

640?wx_fmt=png

  • 该方法首先判断传入的middleware是否是IMiddleware类型,如果是则调用UseMiddlewareInterface

从这段代码中可以看到IMiddlewareFactory负责创建并回收IMiddleware对象

640?wx_fmt=png

MiddlewareFactoryCreate方法中可以看到,IMiddleware实例是从容器中获取的,若容器中找不到则会抛出异常:

640?wx_fmt=png

  • 若是Conventional Middleware则判断传入的middleware是否符合约束

首先判断传入的middleware中是否仅包含一个名称为Invoke或InvokeAsync的公共实例方法

640?wx_fmt=png

其次判断方法的返回类型是否是Task

640?wx_fmt=png

然后再判断,方法的第一个参数是否是HttpContext类型:

640?wx_fmt=png


对于InvokeInvokeAsync仅包含一个HttpContext类型参数的情况用到了反射(ActivatorUtilities.CreateInstance方法中)来构建RequestDelegate

640?wx_fmt=png

对于包含多个参数的情况,则使用了表达式树来构建RequestDelegate

640?wx_fmt=png

完整的代码可以在Github上看到。

Use(Func<RequestDelegate, RequestDelegate> middleware)

上述所有中间件,最终都会调用IApplicationBuilder接口中的Use(Func<RequestDelegate, RequestDelegate> middleware)方法来实现向请求处理管道中注册中间件,该方法在ApplicationBuilder类的实现如下:

640?wx_fmt=png

从上面代码中可以看到,中间件是一个RequestDelegate类型的委托,请求处理管道其实是一个委托列表,请求委托签名如下:

public delegate Task RequestDelegate(HttpContext context);

 


与ASP.NET处理管道的区别

 

 

640?wx_fmt=png

 

传统的ASP.NET的处理管道是基于事件模型的,处理管道有多个IHttpModule和一个IHttpHandler组成。请求处理管道中各个模块被调用的顺序取决于两方面:

  • 模块所注册事件被触发的先后顺序

  • 注册同一事件的不同模块执行先后顺序有Web.config中的配置顺序决定

 

640?wx_fmt=jpeg

 

 

ASP.NET Core的请求处理管道则是有一堆中间件组成,相对ASP.NET更简单。

中间件处理请求和响应的顺序只与其在代码中的注册顺序有关:处理请求按注册顺序依次执行,处理响应按注册顺序反方向依次执行。

其次,在ASP.NET Core中只需使用代码,而无需使用Global.asaxWeb.config来配置请求处理管道。

小结

所谓中间件就是嵌入到应用管道中用于处理请求和响应的一段代码,它主要有两个作用:

  • 处理请求和响应

  • 可以阻止请求发往请求处理管道中的下一个中间件

在ASP.NET Core中,中间件是以RequestDelegate委托的形式体现的。

ASP.NET Core中整个请求处理管道的创建是围绕这种IApplicationBuilder接口进行的,请求处理管道是一个List<RequestDelegate>类型的列表。

推荐阅读

ASP.NET Core Middleware
Factory-based middleware activation in ASP.NET Core
Migrate HTTP handlers and modules to ASP.NET Core middleware
ASP.NET MVC5请求处理管道和生命周期
用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识

原文地址:https://www.cnblogs.com/Cwj-XFH/p/9690728.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NOIP复健计划——动态规划

树形DP [POI2011] DYN-Dynamite 二分KKK check(mid)&#xff1a; 能否选出mmm个点&#xff0c;使得 ∀i为关键点&#xff0c;Minjisselected{dis(i,j)}≤mid\forall i为关键点&#xff0c;Min_{j\ is\ selected}\{dis(i,j)\}\leq mid∀i为关键点&#xff0c;Minj is selecte…

【每日一题】7月6日精讲—平衡二叉树

来源&#xff1a;牛客网&#xff1a; 文章目录题目描述题解&#xff1a;代码&#xff1a;时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 1048576K&#xff0c;其他语言2097152K 64bit IO Format: %lld题目描述 平衡二叉树&#xff0c;顾名思义就…

【DP】晨练计划(ybtoj)

正题 ybtoj 题目大意 给你n个时间点 在第i个时间点跑步有aia_iai​点贡献&#xff0c;但会加一点疲惫值&#xff0c;疲惫值不能超过m 当前疲惫值为x&#xff0c;那么你可以花x点时间来清空疲惫值&#xff0c;当然也可以啥都不干 问你第n个时间后疲惫值为0的最大贡献 解题思…

MATLAB灰色预测

一.灰色预测 1.灰色系统下的灰色预测 <1>什么是灰色系统&#xff1f; 所谓的灰色系统其实就是夹杂在白色系统和黑色系统之中的一种系统&#xff0c;而白色系统就是全部信息已知的系统&#xff0c;黑色系统就是全部信息未知的系统。所以&#xff0c;夹在这两种系统中间…

ASP.NET Core 中的依赖注入

什么是依赖注入软件设计原则中有一个依赖倒置原则&#xff08;DIP&#xff09;&#xff0c;为了更好的解耦&#xff0c;讲究要依赖于抽象&#xff0c;不要依赖于具体。而控制反转(Ioc)就是这样的原则的其中一个实现思路, 这个思路的其中一种实现方式就是依赖注入(DI)。什么是依…

P4357-[CQOI2016]K远点对【K-Dtree】

正题 题目链接:https://www.luogu.com.cn/problem/P4357 题目大意 平面上给出nnn个点&#xff0c;求第kkk远的点对距离。 解题思路 K-Dtree\text{K-Dtree}K-Dtree的模板题&#xff0c;但是这里只有二维&#xff0c;大概是每次根据一个维度把nnn个点分成两半像线段树一样丢到下…

【每日一题】7月7日题目精讲—最短路

来源&#xff1a;牛客网&#xff1a; 文章目录题目描述题解&#xff1a;代码&#xff1a;时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 1048576K&#xff0c;其他语言2097152K 64bit IO Format: %lld题目描述 给一个连通图&#xff0c;每次询问…

【dfs】栅栏的木料(2012特长生 T4)

题目大意 给你n个木板&#xff0c;给你这些木板的长度&#xff0c;你可以把这些木板切开&#xff0c;现在有m个木料&#xff0c;问你最多可以切出多少个木料 解题思路 可以dfs枚举每个木料用哪个木板来切 但这样显然会超时&#xff0c;那么考虑剪枝 1.对于一些木板&#xf…

【c++算法刷题笔记】——洛谷1

2020/2/14-2/16 1. 循环提取一个数的每一位数字 while (d > 0) //d0跳出循环 {xd%10; //x每次为d的个位数 d d / 10; //相当于d每次舍去个位数 }2. cnew创建动态二维数组 int *anew int[n]; //创建动态一维数组 int(* a)[2…

【活动(广州)】office365的开发者训练营

Office 365每月有超过1亿的商业活跃用户&#xff0c;是现有最大的生产力服务。Office 365为开发人员提供了一个令人难以置信的机会&#xff0c;包括业务关键数据和数百万用户&#xff0c;以及一个旨在让人们保持工作流程的平台。作为一名开发人员&#xff0c;您可以使用每天使用…

P5325-[模板]Min_25筛

正题 题目链接:https://www.luogu.com.cn/problem/P5325 题目大意 定义一个积性函数满足f(pk)pk(pk−1)f(p^k)p^k(p^k-1)f(pk)pk(pk−1) 求∑i1nf(i)\sum_{i1}^nf(i)∑i1n​f(i) 解题思路 首先我们可以把f(pk)f(p^k)f(pk)是质数的情况拆成一个222阶的多项式f(x)x2−xf(x)x^2…

牛客网【每日一题】7月8日 Alliances

来源&#xff1a;牛客网 文章目录题目描述题解&#xff1a;代码&#xff1a;时间限制&#xff1a;C/C 5秒&#xff0c;其他语言10秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 树国是一个有n个城市的国家&#xff0c;城市编号…

【bfs】廉价最短路径(2013特长生 T4)

题目大意 给你一个图&#xff0c;每条边有一个代价&#xff0c;让你求0到1在最短路径的前提下的最小代价 解题思路 bfs同时求个最代价 代码 #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #de…

Ocelot简易教程(四)之请求聚合以及服务发现

上篇文章给大家讲解了Ocelot的一些特性并对路由进行了详细的介绍&#xff0c;今天呢就大家一起来学习下Ocelot的请求聚合以及服务发现功能。希望能对大家有所帮助。作者&#xff1a;依乐祝原文地址&#xff1a;https://www.cnblogs.com/yilezhu/p/9695639.html请求聚合Ocelot允…

邓公数据结构C++语言版学习笔记1

1. 对于计算幂2n2^n2n的算法优化 暴力算法时间复杂度O(n)O(n)O(n) __int64 power2BF_I(int n) //幂函数2^n算法&#xff08;蛮力迭代版&#xff09;&#xff0c;n > 0{ __int64 pow 1; //O(1)&#xff1a;累积器刜始化为2^0while (0 < n --) //O(n)&#xff1a;迭代n轮…

【每日一题】7月9日题目 Color

来源&#xff1a;牛客网&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 131072K&#xff0c;其他语言262144K Special Judge, 64bit IO Format: %lld文章目录题目描述题解&#xff1a;代码&#xff1a;题目描述 给一个没有重边的二…

【DP】K星人的语言(2020特长生 T3)

题目大意 给你一个字符串和若干单词&#xff0c;问你最少删除多少字符使其成为若干单词连在一起的字符串 解题思路 设fif_ifi​为前i个位置的最小代价 然后枚举每个单词即可 代码 #include<cstdio> #include<cstring> #include<iostream> #include<al…

HttpClientFactory系列二:集成Polly处理瞬态故障

前言&#xff1a;最近&#xff0c;同事在工作中遇到了使用HttpClient,有些请求超时的问题&#xff0c;辅导员让我下去调研一下&#xff0c;HttpClinet的使用方式已经改成了之前博客中提到的方式&#xff0c;问题的原因我已经找到了&#xff0c;就是因为使用了伪异步&#xff0c…

Loj#6053-简单的函数【Min25筛】

正题 题目链接:https://loj.ac/p/6053 题目大意 定义一个积性函数f(pc)pxorcf(p^c)p\ xor\ cf(pc)p xor c&#xff0c;求∑i1nf(i)\sum_{i1}^nf(i)∑i1n​f(i) 解题思路 异或这个东西不太好搞&#xff0c;要考虑怎么求出ggg数组。 当ppp为质数时f(p)p−1f(p)p-1f(p)p−1&am…

邓公数据结构C++语言版学习笔记——二叉树

二叉树的遍历 一. preorder——先序遍历VLR 1. 递归先序遍历 2. 迭代先序遍历 3.先序遍历图解 二. inorder——先序遍历LVR 1. 递归中序遍历 2.迭代中序遍历 3.迭代中序遍历优化空间复杂度 <1>定义直接后继 <2>借用直接后继优化算法 解释&#xff1a;…