

Asp.Net Core 中间件应用实践中你不知道的那些事
source link: http://www.cnblogs.com/jlion/p/12430522.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、概述
这篇文章主要分享 Endpoint
终结点路由的 中间件
的应用场景及实践案例,不讲述其工作原理,如果需要了解工作原理的同学,
可以点击查看以下两篇解读文章:
1.1 中间件(Middleware)的作用
我们知道,任何的一个web框架都是把http请求封装成一个管道,每一次的请求都是经过管道的一系列操作,最终到达我们写的代码中。那么中间件就是在应用程序管道中的一个组件,用来拦截请求过程进行一些其他处理和响应。中间件可以有很多个,每一个中间件都可以对管道中的请求进行拦截,它可以决定是否将请求转移给下一个中间件。
asp.net core 提供了 IApplicationBuilder
接口来让把中间件注册到asp.net的管道请求当中去,中间件是一个典型的 AOP
应用。 下面是一个微软官方的一个中间件管道请求图:

1.2 中间件和过滤器的区别
Filter
是延续ASP.NET MVC的产物,同样保留了五种的Filter,分别是Authorization Filter、Resource Filter、Action Filter、Exception Filter及Result Filter。
具体可以查看我上次分享的一篇 Asp.Net Core Filter 深入浅出的那些事-AOP 的文章.
根据描述,可以看出中间件和过滤器的功能类似,那么他们有什么区别?为什么又要搞一个中间件呢?
其实,过滤器和中间件他们的关注点是不一样的,也就是说职责不一样,干的事情就不一样。
同作为两个 AOP
利器, Filter
(过滤器)更贴合业务,它关注于应用程序本身,比如你看 ActionFilter
和 ResultFilter
,它都直接和你的 Action
, ActionResult
交互了,是不是离你很近的感觉,那我有一些比如对我的输出结果进行格式化,对我的请求的ViewModel进行数据验证啦,肯定就是用Filter无疑了。它是MVC的一部分,它可以拦截到你Action上下文的一些信息,而中间件是没有这个能力的。
可以看到,每一个中间件都都可以在请求之前和之后进行操作。请求处理完成之后传递给下一个请求
1.3 中间件的使用场景
那么,何时使用中间件呢?我的理解是在我们的应用程序当中和业务关系不大的一些需要在管道中做的事情可以使用,比如身份验证,Session存储,日志记录等。其实我们的 Asp.net core项目中本身已经包含了很多个中间件。比如 身份认证中间件 UseAuthorization()
等系列.
二、中间件实战
需求场景:通过后端记录每一次的访问请求日志,同时需要根据需要排除一些 Controller
或者 Action
不记录请求的日志信息。
思考:经过分析我需要创建一个全局的中间件进行拦截路由,并且写入日志;同时需要添加一个特性 Attribute
进行标注那些 Controller
或者 Action
不需要进行日志记录。
我们来创建 LogsMiddleware
中间件代码,代码如下:
public class LogsMiddleware { private readonly RequestDelegate _next; public LogsMiddleware(RequestDelegate next) { this._next = next; } public async Task Invoke(HttpContext context) { var endpoint = context.Features.Get<IEndpointFeature>()?.Endpoint; if (endpoint == null) { await _next(context); return; } using (var scope = context.RequestServices.CreateScope()) { var _logger = scope.ServiceProvider.GetService<ILogger<LogsMiddleware>>(); var attruibutes = endpoint.Metadata.OfType<NoLogsAttriteFilter>(); if (attruibutes.Count()==0) { _logger.LogInformation($" url:{context.Request.Path}, 访问时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); } //记录 排除的特殊Message 信息 foreach (var attribute in attruibutes) { _logger.LogInformation(attribute.Message); } } await _next(context); } }
NoLogsAttriteFilter
过滤器代码如下:
public class NoLogsAttriteFilter : Attribute { /// <summary> /// 这里加这个主要是把获取到的信息在中间件中打印出来,区分中间件的拦截用处 /// </summary> public string Message = ""; public NoLogsAttriteFilter(string message) { Message = message; } }
Startup
中的代码如下:
public void Configure(IApplicationBuilder app, IWebHostEnvironment 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.UseRouting(); app.UseAuthorization(); app.UseMiddleware<LogsMiddleware>();//添加日志记录中间件 app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }
HomeController
控制器中的两个Action 代码如下::
// 访问该路由会记录访问日志 public IActionResult Index() { return View(); } //访问该路由不会记录访问日志 [NoLogsAttriteFilter("Manage 不需要记录访问日志")] public IActionResult Manage() { return View(); }
这样就自定义日志中间件就已经完成了我上面的需求,不依赖于任何业务独立存在于系统中;从代码中我们可以看到中间件通过 context.Features.Get<IEndpointFeature>()?.Endpoint;
方法获得终结点路由方式进行匹配,并且可以通过 endpoint.Metadata.OfType<NoLogsAttriteFilter>()
方式获得 Action
中的特性信息数据,并通过该拦截进行我的需求
自定义中间件教程文章请点击 自定义中间件官方教程 一文。
现在我们再来印证下我上一篇关于 Asp.Net Core EndPoint 终结点路由工作原理解读 一文 中提及到 UseRouting()
中间件是遍历所有的 Endpoint
终结点路由以匹配当前请求的 Endpoint
终结点路由一说,我把注册 LogsMiddleware
中间件和 UseRouting()
路由中间件代码顺序调整一下,代码如下:
public void Configure(IApplicationBuilder app, IWebHostEnvironment 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(); } // 中间件注册放到了UseRouting() 之前 app.UseMiddleware<LogsMiddleware>();//添加日志记录中间件 app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }
再来看看运行调试的结果如图:

从调试的结果图中可以看出 endpoint
变量是 null;所有需要使用到 Endpoint
终结点路由必须注册在 UseRouting()
中间件之后。
三、官方常用中间件
- 异常/错误处理
当应用在开发环境中运行时:
开发人员异常页中间件 (UseDeveloperExceptionPage
) 报告应用运行时错误。
数据库错误页中间件报告数据库运行时错误。
当应用在生产环境中运行时:
异常处理程序中间件 (UseExceptionHandler
) 捕获以下中间件中引发的异常。
HTTP 严格传输安全协议 (HSTS) 中间件 (UseHsts) 添加 Strict-Transport-Security 标头。 - HTTPS 重定向中间件 (
UseHttpsRedirection
) 将 HTTP 请求重定向到 HTTPS。 - 静态文件中间件 (
UseStaticFiles
) 返回静态文件,并简化进一步请求处理。 - Cookie 策略中间件 (
UseCookiePolicy
) 使应用符合欧盟一般数据保护条例 (GDPR) 规定。 - 用于路由请求的路由中间件 (
UseRouting
)。 - 身份验证中间件 (
UseAuthentication
) 尝试对用户进行身份验证,然后才会允许用户访问安全资源。 - 用于授权用户访问安全资源的授权中间件 (
UseAuthorization
)。 - 会话中间件 (
UseSession
) 建立和维护会话状态。 如果应用使用会话状态,请在 Cookie 策略中间件之后和 MVC 中间件之前调用会话中间件。 - 用于将
Razor Pages
终结点添加到请求管道的终结点路由中间件(带有 MapRazorPages 的UseEndpoints
)。
如果您觉的不错,请微信扫码关注 【dotNET博士】公众号,后续给您带来更精彩的分享

以上如果有错误的地方,请大家积极纠正,谢谢大家的支持!!
Recommend
-
58
URL重写是基于一个或多个预置规则修改请求URL的行为。URL重写在资源位置和访问地址之间创建了一种抽象,这样二者之间就减少了紧密的联系。URL重写有多种适用的场景: 临时或永久移动或替换服务器资源,同时为这些资源...
-
29
1.前言 中间件(middleware)是一种装配到应用管道以处理请求和响应的组件。每个组件:●可选择是否将请求传递到管道中的下一个组件。●可在管道中的下一个组件前后执行工作。请求委托(request
-
22
ASP.NET Core 中间件的配置方法可以分为以上三种,对应的Helper方法分别是:Run(), Use(), Map()。 Run(),使用Run调用中间...
-
11
ASP.NET Core静态文件中间件[1]: 搭建文件服务器虽然ASP.NET Core是一款“动态”的Web服务端框架,但是由它接收并处理的大部分是针对静态文件的请求,最常见的是开发Web站点使用的3种静态文件(JavaScript脚本、CSS样式和图片)。ASP.NET Core提供了3个中间件来处...
-
9
上面的实例演示(搭建文件服务器、条件请求以提升性能和
-
19
ASP.NET Core应用默认的请求处理管道是由注册的IServer对象和HostingApplication对象组成的,后者利用一个在创建时提供的RequestDelegate对象来处理IServer对象分发给它的请求。而RequestDelegate对象实际上是由所有的中间件按照注册顺序创建的。换句话说,这个...
-
22
写在前面 上一篇大家已经粗略接触了解到.NET Core中间件的使用:ASP .Net Core 中间件的使用(一):搭建静态文件服务器/访问指定文件,
-
15
对于NuGet包由“Microsoft.AspNetCore.StaticFiles”提供的3个中间件来说,StaticFileMiddleware中间件旨在处理针对具体静态文件的请求,其他两个中间件(DirectoryBrowserMiddleware和DefaultFilesMiddleware)处理的均是针对某个目录的请求。
-
38
借助路由系统提供的请求URL模式与对应终结点(Endpoint)之间的映射关系,我们可以将具有相同URL模式的请求分发给应用的终结点进行处理。ASP.NET Core的路由是通过EndpointRoutingMiddleware和EndpointMiddleware这两个中间件协作完成的...
-
17
到目前为止,ASP.NET Core提供了两种不同的路由解决方案。传统的路由系统以IRouter对象为核心,我们姑且将其称为IRouter路由。本章介绍的是最早发布于ASP.NET Core 2.2中的新路由系统,由于它采用基于终结点映射的策略,所以我们将其称为终结点路由。终结点路由...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK