理解ASP.NET Core中的中间件

中间件是ASP.NET Core的一个重要特点,ASP.NET Core应用程序之所以能够灵活地处理各种各样的请求,完成都是由于中间件,那么它究竟是怎么一回事呢?

一、理解中间件

ASP.NET Core的一个主要特点是中间件(Middleware),它通过中间件来处理传入的HTTP请求,并将处理结果返回给发起请求的客户端。多个中间件构成了中间件管道(Middleware pipeline),也称为请求管道。之所以称其为管道,是因为请求能够从一个中间件进入另一个中间件,并以相反的顺序再出来,如下图。

对于一个ASP.NET Core应用程序,所有向它发送的请求,都是通过它里面添加的中间件来进行处理并返回响应,比如显示网站的首页、对用户的认证、请求静态文件(CSS、JavaScript文件)等等。

另外,需要注意的是,传入的请求,不一定会遍历到所有添加的中间件,有可能在经过某一个中间件处理时,直接返回响应,而不再继续前进,比如,如果用户没有通过认证,或者程序出现异常时,就不会再继续被下一个中间件处理。

二、Program与Startup

在一个ASP.NET Core应用中,最主要的文件有两个,一个是Program.cs,另一个是Startup.cs,其中Program.cs里包含了程序的入口,即Program类中的Main函数。而Startup.cs文件中的Startup类则是用来配置当前应用程序。

Startup类包含了两个方法,即ConfigureServices和Configure,其中前者主要是用于向依赖注入容器添加服务,而后者则是用于为当前程序配置处理HTTP请求的请求管道;在这个方法里,我们可以根据需要添加多个中间件。

public class Startup
{public void ConfigureServices(IServiceCollection services){// 向依赖注入容器添加服务}public void Configure(IApplicationBuilder app, IHostingEnvironment env){// 配置中间件管道    }
}

三、添加中间件

添加中间件的方法有3种,这3种方法都是通过Configure方法的参数IApplicationBuilder接口所提供的方法实现的,这个接口提供Use、Map以及Run方法,均能够用来添加中间件。

1、Run方法最简单,它仅处理请求,并不会将请求传入下一个中间件。因此,对于如下代码,会直接返回包含一串字符的响应。

app.Run(async (context) =>{    await context.Response.WriteAsync("Hello World!");});

2、Use方法与Run方法不同的是,它在处理请求后,还可以把请求传递给下一个中间件,并由其继续处理。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{app.Use(async (context, next) =>{if (context.Request.Path.Value == "/welcome"){await context.Response.WriteAsync("Hello World!");}else{Debug.WriteLine("中间件 A 开始");// ....await next();// ...Debug.WriteLine("中间件 A 结束");}});app.Run(async (context) =>{await context.Response.WriteAsync("Hello World!");});
}

以上代码的运行结果是:显示“中间件 A 开始” -> 在响应正文中写入信息 -> 显示“中间件A结束。
注意:尽管Use方法能够让下一个中间件继续处理请求,它也可以直接处理,不再继续向前,在上例中如果访问/welcome将直接返回响应。
3、Map方法允许指定一个条件,如果请求符合该条件,则会新建一个分支,并在该分支上继承处理请求,而当请求处理结束后,不返回原来的分支。

public void Configure(IApplicationBuilder app)
{app.Use(async (context, next) =>{  Console.WriteLine("中间件 A:开始");await next();Console.WriteLine("中间件 A:结束");});app.Map(new PathString("/map"),a => a.Use(async (context, next) =>{Console.WriteLine("中间件 B:开始");await next();Console.WriteLine("中间件 B:结束");}));app.Run(async context =>{Console.WriteLine("中间件 C");await context.Response.WriteAsync("Hello world");});
}

当请求/map后,其结果如下:

中间件 A:开始
中间件 B:开始
中间件 B:结束
中间件 A:结束

可以看到,中间件C并未执行。
事实上,除了以上3个方法,ASP.NET Core还提供了UseWhen和MapWhen这两个方法,它们能够以更复杂的方式来添加中间件。

通过上面的介绍,我们可以明白两点,第一,中间件并不复杂,它本质上就是用于处理HTTP请求的一段代码;第二点,中间件的添加顺序很重要,因为它的添加顺序将决定应用程序如何处理HTTP请求。

四、自定义中间件

通过上面的方式添加的中间件,我们可以称为内联中间件(Inline Middleware),这种方式在实际开发中很少见,更常见的方式是创建自定义中间件类,也即,添加一个类,通过这个类来代表中间件并实现其功能。而这个类需要满足两个条件:

第一,它包含一个带有RequestDelegate类型参数的构造函数,这个RequestDelegate类型的参数表示在请求管道中的下一个中间件;

第二,它包含一个Invoke方法,该方法接受一个HttpContext类型的参数,并且这个方法的返回值为Task,这个HttpContext类型的参数即表示传入的HTTP请求。以下是一个典型自定义中间件:

public class CheckRequestPathMiddleware
{private RequestDelegate _next;public CheckRequestPathMiddleware(RequestDelegate requestDelegate){this._next = requestDelegate;}public Task Invoke(HttpContext context){if (context.Request.Path.Value == "/about"){context.Response.ContentType = "text/plain;charset=utf-8";context.Response.WriteAsync("Hello, 这条消息由自定义中间件输出");return Task.CompletedTask;}else{return _next(context);}}
}

当中间件创建好之后,要在Startup类中的Configure方法中把它添加到管道中,只要使用IApplicationBuilder接口的UseMiddleware方法。

app.UseMiddleware<CheckRequestPathMiddleware>();

ASP.NET Core提供了很多中间件,它们能够满足开发Web应用程序时所需要的各种功能,这些中间件包括:MVC、认证、静态文件、HTTPS重定向、CORS等。以下代码显示了一个标准应用程序所添加的中间件。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Home/Error");// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.app.UseHsts();}app.UseHttpsRedirection();app.UseStaticFiles();app.UseCookiePolicy();app.UseMvc(routes =>{routes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}");});
}

以上这些以Use开头的方法均是向请求管道添加相应的中间件。我们可能注意到这些方法并不像我们刚才介绍的添加中间件的方法那样,即要么使用Use/Map/Run等,要么使用UseMiddleware方法。这里需要说明的是,以上这些以Use开头的方法本质上也是使用了UseMiddleware方法来添加中间件的。这些方法只不过是通过额外定义的一个扩展方法来更方便地添加相应的中间件而已。我们同样也可以创建类似的扩展方法,以方便别人使用我们所创建的自定义中间件。

public static class CheckRequestPathMiddlewareExtentions
{public static void UseCheckRequestPathMiddleware(this IApplicationBuilder app){app.UseMiddleware<CheckRequestPathMiddleware>();}
}

通过上面这个方法,我们就可以在Configure方法中直接调用app.UseCheckRequestPathMiddleware方法来添加这个自定义中间件了。

总结
本文简要地介绍了ASP.NET Core中所引入的中间件的概念以及其使用方法,中间件极大地方便了应用程序对HTTP请求的处理。多个中间件构成的管道为ASP.NET Core应用程序提供了更灵活的、更轻量的HTTP请求处理方式。

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

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

相关文章

XGBoost-原理推导(上)

XGBoost简介 XGBoost&#xff08;eXtreme Gradient Boosting&#xff09;是华盛顿大学博士陈天奇创造的一个梯度提升&#xff08;Gradient Boosting&#xff09;的开源框架。至今可以算是各种数据比赛中的大杀器&#xff0c;被大家广泛地运用。 之前的文章我已经介绍了GBDT&a…

redis深度历险_Redis的数据结构(内存具体怎么优化的)

上一篇我们讲解了Redis中SDS的组成以及优势&#xff0c;这一篇我们讨论下Redis中的Hash数据类型是怎么构成的呢&#xff1f;Java中存在HashMap和HashTable的数据类型。而Hash的数据结构可以近似于HashTable&#xff0c;依据数组链表的形式构成。在Redis中&#xff0c;Hash在元素…

.NET Core开发实战(第19课:日志作用域:解决不同请求之间的日志干扰)--学习笔记...

19 | 日志作用域&#xff1a;解决不同请求之间的日志干扰开始之前先看一下上一节的代码// 配置的框架 var configBuilder new ConfigurationBuilder(); configBuilder.AddCommandLine(args); configBuilder.AddJsonFile("appsettings.json", optional: false, reloa…

递归算法(二)-分治法

分治法 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题&#xff0c;这些子问题相互独立且与原问题性质相同。求出子问题的解&#xff0c;就可得到原问题的解。即一种分目标完成程序算法&#xff0c;简单问题可用二分法完成。 分治法解题的一般步骤&#…

自适应滤波器在matlab仿真的程序_电气信息类专业课程之matlab系统仿真 第五章 BPSK通信系统(3)...

继续讲解&#xff01;上一篇文章提出了那么多问题&#xff0c;不知道大家是否能回答上来啊&#xff1f;如果回答不了&#xff0c;有没有去问问度娘呢&#xff1f;程序写完了&#xff0c;回想了一下辅导2017届学生毕业设计的过程&#xff0c;那是真累。我要求他们在现有程序基础…

阿捷外传之Git代码统计:DotNetCore + PowerBI 实现Git仓库日志分析

前言2020年3月初春&#xff0c;虽然春节已经过去一个多月&#xff0c;大街上还未恢复往年的热闹。由于春节前夕突然降临的冠状病毒&#xff0c;导致很多员工无法回到城市复工。春节之后&#xff0c;阿捷所在的公司考虑到复工带来的风险&#xff0c;通知所有员工以远程的方式在家…

递归算法(三)- 回溯法Backtracking

回溯法 回溯法Backtracking&#xff08;找所有的可能&#xff09;递归&#xff1a; 类似枚举&#xff0c;一层一层向下递归&#xff0c;尝试搜索答案。找到答案&#xff1a; > 返回答案&#xff0c;并尝试别的可能未找到答案&#xff1a; > 返回上一层递归&#xff0c;…

一个全栈式的应用集成平台,打破“信息孤岛”

源宝导读&#xff1a;随着企业数字化进程的逐渐深入&#xff0c;企业存在大量的异构系统&#xff0c;各个系统之间信息传输、资源利用困难。本文将介绍明源云ERP为了打破这种“信息孤岛”&#xff0c;而进行的思考与实践。一、前言随着企业信息化进程的逐步深入&#xff0c;互联…

【朝夕技术专刊】Core3.1WebApi_Filter多种注册方式支持依赖注入

欢迎大家阅读《朝夕Net社区技术专刊》第5期我们致力于.NetCore的推广和落地&#xff0c;为更好的帮助大家学习&#xff0c;方便分享干货&#xff0c;特创此刊&#xff01;很高兴你能成为忠实读者&#xff0c;文末福利不要错过哦&#xff01;01PARTCoreFilter多种注册方式在上一…

SQL(一)- 数据库介绍与基础操作

数据库介绍 一、常用的数据库分为两大类&#xff1a; 关系型数据库非关系型数据库&#xff08;NoSql&#xff09; 关系型数据库 概念&#xff1a;是建立在关系模型基础上的数据库&#xff0c;借助于集合代数等数学概念和方法来处理数据库中的数据。 关系型数据库的优势&am…

opencv +数字识别

现在很多场景需要使用的数字识别&#xff0c;比如银行卡识别&#xff0c;以及车牌识别等&#xff0c;在AI领域有很多图像识别算法&#xff0c;大多是居于opencv 或者谷歌开源的tesseract 识别.由于公司业务需要&#xff0c;需要开发一个客户端程序&#xff0c;同时需要在xp这种…

SQL(二)- 基础查询语句

简单的查询语句&#xff08;DQL&#xff09; 下面我们正式来学习查询语句&#xff0c;下面所有查询用到的表均为前面提到的三张表&#xff1a; 员工表中的数据&#xff1a; 部门表中的数据&#xff1a; 薪资表中的数据&#xff1a; 基本查询语句的语法&#xff1a; sele…

SQL(三)- 连接查询

连接查询概念 一、什么是连接查询&#xff1f; 在实际开发中&#xff0c;大部分的情况下都不是从单张表中查询数据&#xff0c;一般都是多张表联合查询最终取出最终结果。在实际再发中&#xff0c;一般一个业务都会对应多张表&#xff0c;比如学生和班级&#xff0c;最起码两…

远程办公也可以很高效

题图&#xff1a;我的站立办公环境因为疫情&#xff0c;全中国人民都过了一个难忘的春节&#xff0c;而身在武汉的我&#xff0c;更是没有出家门半步&#xff0c;坚决做到不过国家添乱。从开始的2月14到后来的2月20日&#xff0c;再到现在的3月10日&#xff0c;官方发布的复工日…

SQL(四) - 子查询和union以及limit分页

子查询概念 什么是子查询&#xff1f;子查询都可以出现在哪里&#xff1f; select语句当中嵌套select语句&#xff0c;被嵌套的select语句是子查询。 子查询可以出现在哪里&#xff1f; select..(select). from..(select). where..(select).1.where子句中使用子查询 案例&a…

ASP.NET Core中的Http缓存

ASP.NET Core中的Http缓存Http响应缓存可减少客户端或代理对 web服务器发出的请求数。响应缓存还减少了 web服务器生成响应所需的工作量。响应缓存由 Http请求中的 header控制。而 ASP.NETCore对其都有相应的实现&#xff0c;并不需要了解里面的工作细节&#xff0c;即可对其进…

SQL(五) - 表的创建以及操作

创建表 建表语句的语法格式&#xff1a; create table 表名(字段名1 数据类型,字段名2 数据类型,字段名3 数据类型,....);MySql常用数据类型 BLOB 二进制大对象&#xff08;存储图片、视频等流媒体信息&#xff09; Binary Large OBject &#xff08;对应java中的Object&…

Istio 2020 年 Roadmap——一切为了商用

原文地址&#xff1a;https://preliminary.istio.io/zh/blog/2020/tradewinds-2020/&#xff0c;由 ServiceMesher 社区翻译。Istio 解决了人们在运行微服务时遇到的实际问题。甚至早期的预发行版本就已经可以帮助用户诊断其体系架构中的延迟&#xff0c;提高服务的可靠性以及透…

SQL(七) - 事务、索引、视图

事务&#xff08;Transaction&#xff09; 3.1、什么是事务&#xff1f; 一个事务是一个完整的业务逻辑单元&#xff0c;不可再分。 比如&#xff1a;银行账户转账&#xff0c;从A账户向B账户转账10000.需要执行两条update语句&#xff1a; update t_act set balance balan…

如何编写高性能的C#代码(二)

使用Benchmark.NET对C# 代码进行基准测试的简介在我以前的文章中[10]&#xff0c;我介绍了该系列文章[11]&#xff0c;在其中我将分享我的经验&#xff0c;同时了解C&#xff03;和.NET Core&#xff08;corefx&#xff09;框架的新性能。在本文中&#xff0c;我想着重于对现有…