ASP.NET Core中间件处理请求管线(翻译)

手写轻量级 ASP.NET 服务框架:深入管线、Handler 与 Module ASP.NET 管线是请求处理的核心机制,其本质是一系列可订阅的生命周期事件链;HttpHandler 承担业务逻辑执行职责,HttpModule 则负责横切关注点(如认证、日志、重写)的拦截与调度。这种职责分离设计赋予了极高的可预测性与定制自由度,尤其适用于统一网关、协议适配、深度监控等工程场景。相比 MVC 的高抽象封装,基于原生管线构建的轻量级服务框架,能精准控制序列化方式、URL 路由时机与请求流劫持点,让开发者真正掌握从 IIS 接入到响应输出的全链路。本文即围绕 ASP.NET 管线与 Http 阅读详情

本片文章将通过一个例子讨论ASP.NET Core请求处理管线。请阅读先前关于ASP.NET Core应用中间件的文章。本章将详细讨论以下几点:

  1. 理解ASP.NET Core请求处理管线
  2. 如何在ASP.NET Core应用中创建并注册多个中间件
  3. 请求处理管线中的中间件执行顺序是怎样的

理解ASP.NET Core请求处理管线

为了理解ASP.NET Core请求处理管线概念,我们修改Startup类中的Configure()方法代码如下。这里我们注册了3个中间件到请求管线中。前2个组件我们是使用Use()扩展方法来注册的,所以他们是可以调用请求管线中下一个中间件。最后一个使用Run()扩展方法来注册,它就是终点组件,即它将不在调用下一个组件了。

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace FirstCoreWebApplication
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
        }
        public void Configure(IApplicationBuilder app)
        {
            app.Use(async (context, next) =>
            {
                await context.Response.WriteAsync("Middleware1: Incoming Request\n");
                await next();
                await context.Response.WriteAsync("Middleware1: Outgoing Response\n");
            });
            app.Use(async (context, next) =>
            {
                await context.Response.WriteAsync("Middleware2: Incoming Request\n");
                await next();
                await context.Response.WriteAsync("Middleware2: Outgoing Response\n");
            });
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Middleware3: Incoming Request handled and response generated\n");
            });
        }
    }
}

现在执行应用看到浏览器上输出如下信息:

理解ASP.NET Core 请求处理管线执行顺序

为了理解这一点,我们使用下面这张图来比较上面的输出。这样更容易理解ASP.NET Core应用请求处理管线。

当流入的HTTP请求道道,第一个中间件接收到,即中间件1在响应流中日志记录下“Middleware1: Incoming Request”。所以我们在浏览器中看到第一行输出该信息。

当第一个中间件记录完该信息,它开始调用next()方法,该方法会触发请求处理管线中的第二个中间件,即中间件2.

第二个中间件日志记录下“Middleware2: Incoming Request”,结果我们看到浏览器上输出该消息紧跟在第一条日志消息。然后第二个中间件调用next()方法,该方法将触发请求管线中第3个中间件,即中间件3。

第3个中间件处理请求并产生响应。所以我们看到浏览器输出“Middleware3: Incoming Request handled and response generated”信息。

中间件3使用Run()扩展方法注册,所以这是一个终点组件。所以从这里开始,请求管线开始反转。意味着从这个中间件返回给第二个中间件,第2个中间件记录下消息: “Middleware2: Outgoing Response”然后传递给第一个中间件,最后第1个中间件记录下如下消息: “Middleware1: Outgoing Response”。

需要记住的关键点

  1. ASP.NET Core请求处理管线包含一系列中间件,按顺序一个接一个调用。
  2. 每个中间件能够在触发下一个中间件函数next()之前或之后做一些操作。中间件也可以决定不调用下一个中间件,这被称为请求管线短路。
  3. 中间件能够访问到流入的请求和流出的响应。
  4. 最关键点在于中间件的执行顺序,是按照他们在Startup类中的Configure方法中加入的顺序执行。这些中间件按顺序触发请求管线中的下一个,响应时按反向顺序传递。为了实现应用的安全,效率及功能,需要严格按照顺序定义中间件。

下一篇文章,将讨论ASP.NET Core中的wwwroot这个目录。本篇尝试解释ASP.NET Core请求处理管线,希望对你理解有所帮助。

译者添加

本文例子中,注册中间件都是在Startup类中的Configure方法中。但使用最新版本ASP.NET Core 6.0模板创建的应用,会发现默认生成的项目文件中并没有Startup.cs这个文件,也找不到Startup类和Configure方法。只有一个Program.cs,相关配置代码都在这里。下面是新版本中,实现一个自定义中间件并注册该中间件的方法。

var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var app = builder.Build();
app.Use(async (HttpContext context, Func<Task> task) =>
{
    await context.Response.WriteAsync("Middleware1: request arrive \n");
    await task.Invoke();
    await context.Response.WriteAsync("Middleare1: Outcomming response \n ");
});
app.Use(async (HttpContext context, RequestDelegate next) =>
{
    await context.Response.WriteAsync("Middleware2: request arrive \n");
    await next.Invoke(context);
    await context.Response.WriteAsync("Middleare2: Outcomming response \n ");
});
(app as IApplicationBuilder).Use(request => async context =>
{
    await context.Response.WriteAsync("Middleware3: request arrive \n");
    await context.Response.WriteAsync("Middleare3: Outcomming response \n ");
});
app.Run();

可以使用上面三种方式使用Use扩展方法来注册中间件(行内匿名方法的方式)。也可以创建一个可复用的类来实现中间件。

    //创建一个类实现自己的中间件,并提供一个扩展方法UseMyMiddleWareHandler
    public static class MyMiddleWareExtensions
    {
        public static IApplicationBuilder UseMyMiddleWareHandler(this IApplicationBuilder app)
        {
            app.UseMiddleware<MyMiddleWare>();
            return app;
        }
    }
    public class MyMiddleWare
    {
        private readonly RequestDelegate _next;
        public MyMiddleWare(RequestDelegate next)
        {
            _next = next;
        }
        public async Task InvokeAsync(HttpContext context)
        {
            await context.Response.WriteAsync("Middleware start \n");
            await context.Response.WriteAsync("Middleware end \n");
        }
    }
    //Program中使用上面的扩展方法注册中间件
    var builder = WebApplication.CreateBuilder(args);
    // Add services to the container.
    var app = builder.Build();
    //由于该自己解决后面没有中间件了,因此在上面实现中间件的InvokeAsync方法中,就不能调用next.Invoke()
    app.UseMyMiddleWareHandler();
    app.Run();

另外一点区别:
dotnet 6.0版本中,app.Run()最后这个方法是WebApplication中的Run方法,查看它的说明如下。即我们的应用必须得有调用这个方法。而Run方法还可以用来配置之前我们提到的端点中间件(即该中间件不能再调下一个中间件)。


我们可以使用Run的一个扩展方法来配置端点中间件,如下:

下图是ASP.NET Core MVC和Razor Pages应用的完整请求处理管线。
在这里插入图片描述
2345截图20221018023540.png

Windows身份认证在ASP.NET企业内网的实战原理与配置 Windows身份认证是基于操作系统安全子系统的企业级身份验证机制,其核心依托NTLM/Kerberos协议与Active Directory集成,实现免登录、单点同步、NTFS细粒度授权等关键能力。相比Forms认证,它将身份校验下沉至IIS内核层,避免密码传输与应用层逻辑耦合,显著提升安全性与性能。技术价值体现在零往返认证、AD组递归授权、Kerberos委派访问后端服务等场景,广泛应用于金融、制造、政务等内网ASP.NET系统。本文聚焦真实产线中的IIS配置、AD查询优化、模拟权限控制及Kerbero 阅读详情

相关推荐

C#性能真相:JIT、GC与抽象税的三重绞杀

托管语言的核心矛盾在于运行时抽象与系统性能的天然张力。C#作为典型现代托管语言,其JIT编译机制带来动态优化能力的同时,也引入不可忽视的启动延迟与CPU预热开销;垃圾回收器虽简化内存管理,却以Stop-The-World暂停和代际晋升不确定性为代价;而LINQ、async/await、字符串插值等高级语法糖,在提升开发效率的同时,实则层层叠加运行时开销——即所谓‘抽象税’。这些机制共同构成.NET应用在客户端响应、服务端延迟、基础设施确定性等关键场景下的性能瓶颈根源。本文聚焦C#真实世界性能表现,结合WPF

491

aspnet core中间件 短路 Response.WriteAsync正确用法

使用 Response.WriteAsync()和Response.StatusCode 定义的body和code时,如果不按套路出牌就会导致body不显示,正确的用法是,在aspnetcore3.1的中间件,在短路时,如果需要自定响应的内容和code,需要注意的问题。在stack overflow上回答了一个问题,随便在这记录下。

m0_62367247的博客 2272

C#跨平台运行方案深度解析:脱离.NET Framework 2.0与飞信虚拟机探秘

回顾这一路,C# 从 Windows 专属语言,到借助 Mono 走向移动端,再到 .NET Core 实现全平台统一,最终在 .NET 5+ 中完成大一统。如今的 .NET 不只是一个运行时,而是一整套现代化开发平台:- 支持 AOT 编译,启动快如闪电⚡- 内置 HTTP/3、System.Text.Json 高性能库🔥- 能编译成 WebAssembly,跑在浏览器里🌐- 甚至可以生成原生二进制,嵌入 Linux 内核模块?🤔(开玩笑的)

weixin_42514540的博客 805

WTM(ASP.NET 5 or 6)发布为Windows服务和使用bat方式启动

WTM(ASP.NET 5)发布为Windows服务和使用bat方式启动

sxy_student的博客 1254

DELL SC存储扩容避坑指南:6Gb vs 12Gb扩展柜混插的真相

本文深入解析DELL SC存储扩容中6Gb与12Gb扩展柜混插的核心规则与性能影响。文章指出,从SCOS 7.3版本起允许混插,但整个SAS环路速率将降至最低设备水平,尤其在12Gb控制器上接入6Gb扩展柜会严重拖累性能。指南提供了清晰的兼容性矩阵、实战操作流程及关键避坑清单,帮助管理员安全、高效地完成存储扩容。

weixin_28314575的博客 458

简易电梯控制系统设计(两层楼)(

(电子科技大学 数字系统实验二 结课验收项目 ) 题目要求:

m0_48801027的博客 1万+

AspNetCore源码之WebHost.cs类

Microsoft.AspNetCore.Hosting.Internal命名空间 WebHost.cs源码 // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for...

极客神殿 805

SCCM实战指南:从零搭建企业级Windows自动化部署平台

本文提供了一份详细的SCCM实战指南,手把手教你从零搭建企业级Windows自动化部署平台。内容涵盖环境规划、AD架构扩展、SQL Server配置、SCCM主站点安装,以及最终实现操作系统镜像的自动化部署,旨在帮助IT管理员彻底告别手动装机,实现高效、规范的Windows设备批量管理。

weixin_29251337的博客 637

ASP.NET Core 源码阅读笔记(3) ---Microsoft.AspNetCore.Hosting

有关Hosting的基础知识      Hosting是一个非常重要,但又很难翻译成中文的概念。翻译成:寄宿,大概能勉强地传达它的意思。我们知道,有一些病毒离开了活体之后就会死亡,我们把那些活体称为病毒的宿主。把这种概念应用到托管程序上来,CLR不能单独存在,它必须依赖于某一个进程,我们把这种状况称之为:CLR必须寄宿于某一个进程中,而那个进程就是宿主。    ASP.NET Core...

weixin_34280237的博客 601

无参考图像质量评估方法:BRISQUE、RankIQA、DIQA

常用的图像质量评估(IQA)分为无参考和有参考两种类型。常见的有参考图像质量评估方法有PSNR,SSIM以及VMAF。其中vmaf是针对视频来讲的,在它的评价方法里面添加了一些时域信息,如果应用于单张图片,需要做一些处理,如去除时域信息。有参考意味着图像质量是以参考图为基准。基于参考图像都是高清图像的假设,这些评价方法已经广泛应用于图像压缩以及图像传输、拼接之类的处理后图像的质量,假如这张参考图的质量本身就比较渣,那么该评价指标可信度就大大降低。

weixin_51732791的博客 3189

python123题目——摩尔斯电码转换

类型:列表元组。

m0_62488776的博客 4414

asp.net core 中间件(翻译)

准备翻译dotnet tutorial网站上一些dotnet方面的知识文章。先从中间件开始,原文地址: ASP.NET Core Middleware with Examples本文主要讨论以下与中间件相关概念中间件是一种软件组件(技术上仅仅是一些C#的类),聚合到应用管线用来处理Http请求和响应。每个中间件执行以下任务:中有许多内置中间件已经可以直接使用。你也可以在你的应用中根据需要创建自己的中间件。最重要的是,一个给定的中间件只专注一个目的:即完成一个职责。应用中使用中间件的一些例子:中间件通常是我们

极客神殿 771

OTFS 消息传递算法信号检测【附matlab代码详解】

OTFS 消息传递算法方面的一些浅浅理解。

Cuby的博客 4008

ASP.NET管线驱动的轻量级服务框架设计与实现

HTTP请求处理管线是ASP.NET最底层、最稳定的核心机制,它定义了从请求进入IIS到响应返回客户端的完整生命周期。理解管线原理,意味着掌握HttpModule与HttpHandler的职责边界、24个关键事件点的触发时机,以及HttpContext等核心对象的生命周期管理。这种底层认知不仅支撑高性能Web服务开发,更赋能自定义路由、GZIP双向压缩、RESTful动词模拟等工程实践。本文以一个700行纯原生API实现的服务框架为载体,深入剖析基于HttpApplication的管线驱动架构,涵盖服务发现

diedangxiang4092的博客 469

Unity 面试篇|(四)Unity性能优化篇 【全面总结 | 持续更新】

Unity中,CPU准备好需要绘制的元素,对底层图形程序接口进行调用的过程,每次引擎准备数据并通知GPU的过程称为一次Draw Call。DrawCall越高对显卡的消耗就越大。降低DrawCall的方法:动态合批静态合批降低shader的等级特性场景优化策略——遮挡技术。rectMask2D替代Mask。

游戏开发小Y的博客 13万+

句向量(句嵌入)模型sent2vec的训练及应用

本文讨论NLP中的句向量模型(sent2vec),也就是将一个完整的句子映射成一个实数向量的技术。这方面已经发表的成果也是比较多的,本文中所涉及的技术主要源自NAACL 2018的一篇论文,其中提出的sent2vec模型可以理解为词嵌入技术中经典的CBOW方法的扩展,该所谓的扩展中一个重要改进就是引入了n-gram

白马负金羁 1万+

简明 ASP.NET Core 手册

编者:在4月份推送过这篇文章 简明 ASP.NET Core 手册 ,今天再次推荐这篇文章,是因为原作者更新到了新版本1.1.0,改动很大,几乎所有章节都有很大程度的调整...

dotNET跨平台 1473

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

ASP.NET技术写作手记:从基础细节到认知地图

ASP.NET作为经典的Web开发框架,其核心价值不仅在于语法和API,更在于对请求生命周期、状态管理、配置机制等底层原理的深刻理解。掌握Request.Params取值顺序、HttpHandler映射规则、Cache穿透防护等关键细节,是避免线上故障的基础能力;而将这些知识点组织成可检索、可复用的‘技术认知地图’,则体现了工程化写作的真正价值。这类内容既服务于初学者快速定位问题,也支撑资深开发者构建系统性调试能力。本文聚焦ASP.NET中那些文档未明说、但生产环境高频踩坑的技术细节,结合真实故障排查与性能

unixboy 484

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

little-aspnetcore-book:项目的核心功能/场景

little-aspnetcore-book:项目的核心功能/场景 《简明 ASP.NET Core 手册》旨在帮助开发者了解并掌握 ASP.NET Core 2.0,这是一个用于构建 Web 应用和 API 的框架。 项目介绍 《简明 ASP.NET Core 手册》是由 Nate Barbettini 著写,windsting 和 yuyi 翻译的开源项目。该项目以创作共用署名 4.0 国际许...

gitblog_00021的博客 855

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Java与.NET程序员的本质差异:工程操作系统级对比

Java和.NET早已超越编程语言范畴,演变为两套深度耦合基础设施、运维体系与开发范式的‘工程操作系统’。其核心差异源于运行时设计哲学——JVM追求跨平台抽象一致性,CLR强调API契约下的平台行为可预期;构建体系上,Maven依赖中央权威保障可重现性,NuGet采用联邦自治提升企业可控性;应用生命周期中,Spring的IoC容器以插件化解耦见长,ASP.NET Core中间件管道则以执行路径透明取胜。这些底层分野直接决定分布式事务处理、实时通信性能、Windows生态集成等关键场景的技术选型。理解Java

SailingAptech的专栏 547

OpenDeepWiki v2.0.0 预览版发布:AI驱动的代码知识库,迎来架构级进化

以内容生成器为例,它对 AI 有严格的约束:禁止编造代码示例(必须从实际源文件提取)、强制源码归属(每个代码块必须附带引用链接)、Mermaid 图表必须反映真实代码结构、工具调用是强制的(AI 必须使用 Git 读取和搜索工具)。这不是一次简单的功能迭代——我们几乎重写了整个系统的核心架构,从后端的 .NET 10 + Semantic Kernel 升级、前端的 Next.js 16 重构,到全新的增量更新引擎、多平台聊天系统、MCP 协议支持,每一个模块都经历了深度打磨。

dotNET跨平台 125

Unity跨平台开发核心:.Net运行时、IL2CPP与Mono后端深度解析

在软件开发领域,跨平台技术是实现代码一次编写、多端运行的关键。其核心原理在于通过中间层抽象,将高级语言代码转换为平台无关的中间表示,再由各平台的运行时环境执行。.Net框架正是这一理念的杰出代表,其公共语言运行时(CLR)和中间语言(IL)机制构成了跨平台的技术基石。对于游戏开发而言,Unity引擎深度集成了.Net生态系统,通过Mono和IL2CPP两种脚本运行时后端,将C#代码高效部署到iOS、Android、PC等多元平台。理解.Net运行时与Unity的协作机制,不仅能优化游戏性能、解决平台兼容性问

cnracht8153的博客 287

微软技术周报·2026-08-24~2026-08-31——.NET11 Preview7最后一个预览版、AI Agent基础设施全面走向GA与治理化

微软技术周报:.NET 11功能冻结前最后一版Preview 7发布,C#带标签break、union模式改进,Runtime Async性能飞跃;AI Agent全面GA与治理化(Agent Plugins 1.0、VS 2026组织级Agent、Copilot Studio迁移Entra Agent ID);Windows 11 26H2进入Release Preview,预计9月底推送。

海盗Sharp的博客 965

技术博客如何建立真实信任:从做人到程序员的三阶成长

技术内容的本质不是知识搬运,而是可信认知的共建。当开发者面对生产故障、版本兼容性争议或性能数据质疑时,真正起作用的不是炫技的架构图,而是可验证的环境声明、可复现的代码实测、可追溯的根因分析——这正是‘做人→技术人员→程序员’三阶跃迁所锚定的核心能力。其中,‘做人’体现为信息溯源与边界声明,‘做技术人员’指向问题建模与跨栈决策,‘做程序员’则落于契约化编码与可维护性设计。尤其在.NET等强生态一致性技术栈中,这种分层递进的实践路径,能系统性对抗‘概念悬浮症’与‘教程体疲劳’,让每一篇内容都成为可嵌入工程现场的

dingguayi7025的博客 483

Python图像绘制四层架构:数据映射、坐标系统、渲染引擎与输出协议

在Python可视化中,图像并非简单‘画图’,而是数据经由多层抽象转换后的结果。从基础概念看,matplotlib本质是一套视觉表达的分层系统:数据需先映射为视觉通道(如颜色、大小),再绑定到特定坐标系(线性/对数/极坐标等),继而交由渲染引擎(Agg/Cairo/Matplotlib Cairo)编译为像素或矢量指令,最终按输出协议(PNG/PDF/SVG)固化为文件。这一过程深刻影响核密度估计曲线的细节呈现、时序数据的动态刷新精度,以及工业控制中模糊隶属度图的边界锐度。理解这四层结构,才能摆脱‘调参式绘

weixin_33834910的博客 444
上一篇: asp.net core 中间件(翻译)
下一篇: 表达式树(一)
.NET跨平台
博客等级 码龄15年 6066粉丝 738原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值