Asp.Net Core 请求管道中间件之Middleware

news/2025/12/4 2:33:53/文章来源:https://www.cnblogs.com/pengboke/p/19304578

前言

中间件(Middleware)

概念

中间件是 ASP.NET Core 请求处理管道(pipeline) 中的一段可插拔组件,接收 HttpContext、执行任意逻辑、并决定是否把请求交给管道中的下一个中间件。管道呈“洋葱模型”(请求顺序进入,响应倒序返回)。

调用签名核心是:RequestDelegate next -> Task Invoke(HttpContext context)

中间件就是请求管道里的“拦路插件”,每个请求经过它,它可以拦截、修改、放行或终止请求。

1.执行流程

  • 注册顺序决定请求进入的顺序。

  • 每个中间件要决定是否 await next(context)(放行)或不调用 next(短路/终止)。

  • 请求走入时是顺序;响应返回时是逆序(栈式回退)。

  • 每个中间件既可以在请求前处理逻辑,也可以在请求后处理逻辑。

请求 -> Middleware1 -> Middleware2 -> Middleware3 -> Endpoint
响应 <- Middleware3 <- Middleware2 <- Middleware1

image-20251115220546746

2.实现方式

RequestDelegate 是中间件的核心,它接收一个 HttpContext,返回一个 Task

中间件管道本质上是 RequestDelegate 链

每个中间件通过调用 await next(context) 来传递请求。

public delegate Task RequestDelegate(HttpContext context);

2.1内联委托方式(Lambda/RequestDelegate)

直接在 Configure 中写 Lambda 表达式,RequestDelegate 链的最轻量写法。

特点

  • 快速、轻量
  • 不可复用
  • 适合简单逻辑、调试或快速原型
app.Use(async (context, next) =>
{Console.WriteLine("请求前逻辑");await next(); // 调用下一个中间件Console.WriteLine("响应后逻辑");
});

示例

Program中通过委托建立中间件

image-20251116170908801

请求http://localhost:5004/WeatherForecast接口,可以看到中间件执行逻辑

请求前逻辑
执行请求中...
响应后逻辑

image-20251116171127156

2.2类中间件方式(RequestDelegate+Invoke/InvokeAsync)

自定义中间件类,通过构造函数注入 RequestDelegate next,实现 InvokeAsync(HttpContext) 方法。

特点

  • 灵活、可复用
  • 支持依赖注入(构造函数注入服务)
  • 最常用的自定义中间件实现方式
public class CustomMiddleware
{private readonly RequestDelegate _next;public CustomMiddleware(RequestDelegate next){_next = next;}public async Task InvokeAsync(HttpContext context){Console.WriteLine("CustomMiddleware请求前逻辑");await _next(context); // 调用下一个中间件Console.WriteLine("CustomMiddleware响应后逻辑");}
}

调用方式app.UseMiddleware<MyMiddleware>();

示例

自定义中间件CustomMiddleware

image-20251116171644164

请求接口,可以看到CustomMiddleware请求逻辑

委托中间件请求前逻辑
CustomMiddleware请求前逻辑
执行请求中...
CustomMiddleware响应后逻辑
委托中间件响应后逻辑

image-20251116171730880

2.3接口(IMiddleware)

IMiddleware 是 ASP.NET Core 自带的接口化中间件实现方式,通过 DI 容器管理生命周期和依赖,简化传统中间件类的实现

特点

  • 生命周期由 DI 管理(Transient/Scoped/Singleton)
  • 不需要手动保存 _next
  • 支持复杂依赖注入,适合大型中间件
public interface IMiddleware
{Task InvokeAsync(HttpContext context, RequestDelegate next);
}public class MyMiddlewareWithDI : IMiddleware
{private readonly ILogger<MyMiddlewareWithDI> _logger;public MyMiddlewareWithDI(ILogger<MyMiddlewareWithDI> logger){_logger = logger;}public async Task InvokeAsync(HttpContext context, RequestDelegate next){_logger.LogInformation("请求前逻辑");await next(context); // 调用下一个中间件_logger.LogInformation("响应后逻辑");}
}

调用方式

// 先注入DI
services.AddTransient<MyMiddlewareWithDI>();
// 再注册中间件
app.UseMiddleware<MyMiddlewareWithDI>();

示例

新增CustomDIMiddleware实现IMiddleware

image-20251116201322994

然后先通过AddTransient<CustomDIMiddleware>()注册到DI,后面再使用UseMiddleware注册中间件CustomDIMiddleware

委托中间件请求前逻辑
CustomMiddleware请求前逻辑
CustomDIMiddleware请求前逻辑
执行请求中...
CustomDIMiddleware响应后逻辑
CustomMiddleware响应后逻辑
委托中间件响应后逻辑

image-20251116172423843

2.4RequestDelegate 工厂方式(高级方式)

将中间件逻辑封装成返回 RequestDelegate 的方法。动态生成中间件、框架内部使用。

特点

  • 高度灵活、可复用
  • 可动态生成中间件
  • 底层原理仍然是 RequestDelegate 链
public static class CustomMiddlewareFactory
{public static RequestDelegate CreateMiddleware(RequestDelegate next){return async context =>{Console.WriteLine("CustomMiddlewareFactory请求前逻辑");await next(context);Console.WriteLine("CustomMiddlewareFactory响应后逻辑");};}
}

调用方式

app.Use(CustomMiddlewareFactory.CreateMiddleware);

示例

新建自定义中间件工厂(CustomMiddlewareFactory),然后提供一个创建RequestDelegate的方法

image-20251116202241418

然后使用Use方法调用,Use方法接收一个参数是RequestDelegate并且返回RequestDelegate的委托,其实和委托方式调用蕾西,这里只是封装起来了

委托中间件请求前逻辑
CustomMiddleware请求前逻辑
CustomDIMiddleware请求前逻辑
CustomMiddlewareFactory请求前逻辑
执行请求中...
CustomMiddlewareFactory响应后逻辑
CustomDIMiddleware响应后逻辑
CustomMiddleware响应后逻辑
委托中间件响应后逻辑

image-20251116202322077

2.5内置扩展方法中间件(Use系列)

框架自带中间件封装,例如:

// 路由
app.UseRouting();
// 认证
app.UseAuthentication();
// 授权
app.UseAuthorization();
// 执行路由匹配后的请求处理
app.UseEndpoints(endpoints => { ... });

特点

  • 封装 RequestDelegate 或类中间件
  • 使用方便,集成 MVC / Minimal API
  • 灵活性略低

2.5总结

关于中间件的执行流程,这里调试一遍就很明显了:

中间件按注册顺序依次执行“请求前逻辑”,到达终点后再按相反顺序依次执行“响应后逻辑”,形成典型的洋葱模型(先进后出、后进先出)。

委托中间件请求前逻辑
CustomMiddleware请求前逻辑
CustomDIMiddleware请求前逻辑
CustomMiddlewareFactory请求前逻辑
执行请求中...
CustomMiddlewareFactory响应后逻辑
CustomDIMiddleware响应后逻辑
CustomMiddleware响应后逻辑
委托中间件响应后逻辑

总结

  • ASP.NET Core 中间件都是 RequestDelegate 链

  • _next 指向下一个中间件,形成管道链

  • 每个中间件可以在请求前/响应后处理逻辑

  • 不同实现方式只是 封装形式、复用性、DI 生命周期管理 不同

实现方式 核心机制 调用方式 特点
内联委托 / Lambda RequestDelegate app.Use(...) 快速、轻量,不可复用
类中间件 + Invoke 类 + RequestDelegate app.UseMiddleware<T>() 灵活、可复用,支持依赖注入
实现 IMiddleware 接口 IMiddleware.InvokeAsync app.UseMiddleware<T>() + DI 生命周期可控,支持复杂依赖
RequestDelegate 工厂 返回 RequestDelegate app.Use(...) 高度灵活,可动态生成
内置扩展方法 框架封装 RequestDelegate app.UseXxx() 使用方便,集成 MVC / Minimal API

3.UseRunMapUseWhen

  • Use:标准,多数中间件用 await next() 放行。

  • Run终端中间件,不接 next,写完后不会再调用后续中间件(短路)。

  • Map / MapWhen:基于路径或条件分支路由,创建子管道(可用于多态处理)。

  • UseWhen:条件中间件,满足条件时在子管道内执行 next,不满足则略过。

方法 是否可放行 作用范围 匹配条件 常见用途
Use 可放行/短路 全局管道 日志、认证、异常处理、请求处理
Run 不放行 全局管道/终端 健康检查、默认响应、短路请求
Map 可放行/短路 子管道 基于路径 分模块处理不同 URL 分支
UseWhen 可放行/短路 子管道 任意条件 条件化中间件,如仅对 API 或特定 header 生效

4.应用场景

  • 全局异常捕获(UseExceptionHandlerDeveloperExceptionPage

  • 日志/请求追踪/CorrelationId(Inject TraceId)

  • 身份认证与授权(JWT、Cookies)

  • CORS、RateLimiting、RequestSizeLimit

  • Static Files、Response Compression、Response Caching

  • HTTPS 强制、HSTS、Content-Security-Policy header 插入

  • Body 读取、请求重写(Rewrite)、路径重写(UsePathBase、RewriteOptions)

  • 流量劫持(Proxy headers)、IP 限制

5.总结

中间件是 ASP.NET Core 请求管道的插件

顺序和调用 next() 决定请求响应流程

Use 可放行,Run 终止,Map/UseWhen 创建子管道

常用于日志、异常、认证、CORS、限流、压缩等横切关注点

6.eshop的中间件

eshop中没有单独封装中间件,而是使用了MediatR命令管道统一处理业务命令的日志、参数验证、管道。

中间件是AspNetCore中很重要的组成,eshop中没有封装使用,但我还是再次学习了一遍

image-20251115232940864

📌 创作不易,感谢支持!

每一篇内容都凝聚了心血与热情,如果我的内容对您有帮助,欢迎请我喝杯咖啡☕,您的支持是我持续分享的最大动力!

💬 加入交流群(QQ群):576434538

微信打赏

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

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

相关文章

Git推送从失败到成功的解决方案

问题描述 今天在尝试将本地代码推送到GitHub远程仓库时,遇到了推送失败的问题。使用git push命令后,出现了以下错误: fatal: unable to access https://github.com/guchen66/IT.Tangdao.Core.git/: OpenSSL SSL_rea…

Microsoft-Store-error

Microsoft-Store-error导航 (返回顶部)1. Store初始化失败1.1 为何要卸载Edge 1.2 如何卸载Edge 1.3 为何删除Edge会影响微软商店2. 微软商店无法联网2.1 解除网络隔离的办法有:3. CheckNetIsolation解除网络隔离3.1 查…

STM32 HAL库 硬件IIC 从机一些问题整理(转载)

一、从机双地址,在回调函数中获取主机访问的地址:void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle) {uint16_t slaveaddrcode = I2C_GET_ADDR_MATCH(I2cHandle);printf("R:%d\r\n",sl…

本地人推荐的火锅,天台火锅/麻辣火锅/老火锅/市井火锅/川渝火锅约会地点推荐榜单

专业视角下的川渝火锅团建选址指南 随着企业团建需求的多元化发展,川渝火锅凭借其独特的社交属性与浓郁的文化氛围,已成为企业团建活动的优选场所。本文基于市场调研数据与消费者反馈,从空间容量、服务质量、特色体…

OBDSTAR P003+ Kit for DC706 Tablets: Simplify ECU, EEPROM, Flash IMMO Data Diagnostics Programming

Troubleshooting ECU & IMMO Challenges on European/American Cars? Meet the OBDSTAR P003+ Kit The Pain Point: Decrypting ECU & IMMO Data on European/American Vehicles For European and American m…

全程复盘:一次枚举值永远 Cloud2的坑——从玄学随机到只读属性

问题描述 在 .NET 6 + WPF 程序中,使用 TangdaoDataFaker<MusicInfo>.Build(200000) 生成测试数据时,控制台 20 条并行日志显示 QQ / Cloud / Kugou 随机分布,但 DataGrid 界面整屏只显示 Cloud2。同一套代码…

M726芯片

根据您提供的《M726 数据手册》,我为您整理了该芯片的关键性能参数,并列出了性能相近的竞品型号及价格参考(基于公开市场信息,实际价格以供应商报价为准):M726 芯片核心性能摘要 类别 参数内核 ARM Cortex-M0,最…

Fast Easy Electric Oil Siphon Pump: Professional Fluid Transfer for Cars, Motorcycles Boats

The Hidden Challenges of Fluid Transfer: Why Mechanics and Car Owners Need a Better Solution Anyone who’s ever drained engine oil, changed coolant, or refilled a motorcycle’s fuel tank knows the frus…

AutoCloseable接口 try-with-resources 、 try-catch-finally

在学习过程中发现了这样一段注释/*** 实现了 AutoCloseable 接⼝的类,在 try() ⾥声明该类实例的时候,在 try 结束后⾃动调⽤的 close ⽅法,这个动作会早于* finally ⾥调⽤的⽅法,不管是否出现异常,try() ⾥的实…

第44天(中等题 数据结构)

打卡第四十四天 2道中等题题目:思路:以每个点为中心,统计与它距离相同的点对数量 代码: class Solution { public:int numberOfBoomerangs(vector<vector<int>>& points) {int ans = 0;int n = po…

rizhi

rizhicat /tmp/ray/session_latest/logs/dashboard_agent.log

element-plus el-select

<template><div class="app"><h4>=========默认情况下的select组件在设置collapse-tags-tooltip后,只有在鼠标移入折叠标签后才显示文本</h4><el-selectmultiplecollapse-tagsc…

centos6.9编译安装python37——SSL 模块缺失、GCOV 链接错误,以及 Bash 命令缓存混乱

安装参考这篇 https://www.cnblogs.com/opsprobe/p/11266939.html 🚀 Python 编译与环境部署深度指南:告别 SSL 缺失和 Bash 缓存困扰 📝 导言 在 Linux 系统上从源码编译安装 Python,尤其是在企业级环境(如 Ce…

在 Windows 上本地部署 ComfyUI + zImage Turbo 模型(低显存友好)

原文:https://www.cnblogs.com/zwj/p/19304354/ai_local_zimg我是觉得我原文写的可能比较乱,于是让AI整理了一下我的原文,下方内容就是QwenMax根据我原文的内容生成的,仅供参考。 在 Windows 上本地部署 ComfyUI +…

sg.取消按钮焦点框

在PySimpleGUI中,按钮上的虚框通常是由焦点指示器(focus indicator)引起的。要取消这个虚框,可以通过以下两种方法实现: 方法1:禁用按钮的焦点属性 在按钮参数中添加 focus=False,直接禁用焦点效果: import Py…

代码随想录Day27_贪心1

代码随想录Day27_贪心1分发饼干 代码 class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end());sort(s.begin(), s.end());int index = s.s…

Day10-20251203

本文介绍了Java中变量、常量及其命名规范。主要内容包括:1)变量的定义与声明语法,强调Java是强类型语言;2)变量的三种作用域(类变量、实例变量、局部变量)及示例代码;3)常量的定义方式(使用final关键字)和命…

面向人机文明的价值协同:理论、实践与评估的完整框架

面向人机文明的价值协同:理论、实践与评估的完整框架 摘要:本文系统性地整合了关于“AI元人文构想”的完整论述,旨在应对人工智能自主性增强所带来的根本性挑战:如何与AI建立可验证、可进化、可信任的价值协同关系…

251203 完成比完美重要

今天运气可以,遇到了直拍侠,直接买了我的自行车。没有多一句话,就成功成交了。开心,希望后面继续 做完纠结了半天,还是决定换一个手机,换了华为荣耀500pro,长得还挺好看的,明天就能拿到了。还是不用苹果了。 准…

python调用大模型api来进行对话

一、Openai的接口调用 pip包下载pip install openai配置sk,urlOPENAI_API_KEY = sk-xxxxxOPENAI_BASE_URL = https://api.openai.com/v1接口调用import os from flask import Flask, jsonify from openai import Open…