当前位置:网站首页>ASP.NET 6 中间件系列 - 自定义中间件类
ASP.NET 6 中间件系列 - 自定义中间件类
2022-04-23 03:02:00 【dotNET跨平台】

这篇文章是 ASP.NET 6 中间件系列文章的第2部分,点击这里可以阅读第1部分。
在上一篇文章中,我们讨论了什么是中间件,它的作用是什么,以及在 ASP.NET 6 应用管道中添加中间件的简单方法。
在这篇文章中,我们将在这些基础上来扩展构建一些自定义中间件类。
示例项目
在 GitHub 上可以获得这篇文章涉及到的代码:
https://github.com/zilor-net/ASPNET6Middleware/tree/Part2
标准中间件结构
与我们在第1部分中所做的不同,大多数时候我们希望中间件是独立的类,而不是在 Program.cs 文件中创建。
让我们回顾一下第1部分的内容,一个响应“Hello Dear Readers!”内容的中间件?
app.Run(async context =>
{
await context.Response.WriteAsync("Hello Dear Readers!");
});
接下来,让我们创建一个自定义中间件类来实现同样的效果。
中间件类的基础知识
下面是一个空类,我们将用于这个中间件:
namespace ASPNET6Middleware.Middleware
{
public class SimpleResponseMiddleware
{
}
}
中间件类由三部分组成:
首先,任何中间件类都必须拥有RequestDelegate类型的私有成员实例,该实例由类的构造函数填充。
RequestDelegate代表管道中的下一个中间件:
namespace ASPNET6Middleware.Middleware
{
private readonly RequestDelegate _next;
public SimpleResponseMiddleware(RequestDelegate next)
{
_next = next;
}
}
其次,这个类必须有一个async方法InvokeAsync(),它接受一个HttpContext类型的实例作为它的第一个参数:
public class SimpleResponseMiddleware
{
private readonly RequestDelegate _next;
public SimpleResponseMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
//...Implementation
}
}
第三,中间件必须有自己的实现。对于这个中间件,我们要做的就是返回一个自定义的响应:
public class SimpleResponseMiddleware
{
private readonly RequestDelegate _next;
public SimpleResponseMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
await context.Response.WriteAsync("Hello Dear Readers!");
}
}
注意:在InvokeAsync()方法中,大多数中间件都会调用await next(context);,任何不这样做的中间件都会是一个终端中间件,它代表着管道的终结,它之后的中间件都不会执行。
向管道中添加中间件
此时,我们可以使用UseMiddleware<>()方法,将这个中间件类添加到 Program.cs 文件中的 app 中:
app.UseMiddleware<LayoutMiddleware>();
对于简单的中间件类,这就足够了。
然而,我们更加常用的方式是使用扩展方法,而不是直接使用UseMiddleware<>(),因为这可以为我们提供一层更加具体的封装:
namespace ASPNET6Middleware.Extensions
{
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseSimpleResponseMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<SimpleResponseMiddleware>();
}
}
}
然后我们可以像这样使用这个扩展方法:
app.UseSimpleResponseMiddleware();
这两种方法都是正确的,但是我个人更喜欢扩展方法的清晰性和可读性。
构建日志中间件
在第1部分时就介绍过,中间件最常见的场景之一是日志记录,特别是记录请求路径或响应头、响应体等内容。
LoggingService 类
我们将构建一个日志中间件类,它只做两件事:
记录请求路径。
记录唯一响应头。
首先,我们必须创建接口ILoggingService和类LoggingService。
namespace ASPNET6Middleware.Logging
{
public class LoggingService : ILoggingService
{
public void Log(LogLevel logLevel, string message)
{
// 日志具体实现省略
}
}
public interface ILoggingService
{
public void Log(LogLevel level, string message);
}
}
然后我们需要在 Program.cs 中将LoggingService添加到应用程序的Services集合中:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddTransient<ILoggingService, LoggingService>();
中间件类也像普通类一样可以注入服务。
LoggingMiddleware 类
现在我们需要一个LoggingMiddleware类来做日志。
首先,让我们为LoggingMiddleware类创建好中间件结构,它在构造函数中接受一个ILoggingService的实例作为参数:
namespace ASPNET6Middleware.Middleware
{
public class LoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILoggingService _logger;
public LoggingMiddleware(RequestDelegate next, ILoggingService logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
//...
}
}
}
我们的任务是记录请求的路径和响应的唯一头,这意味着在await next(context)的前后都有代码:
namespace ASPNET6Middleware.Middleware
{
public class LoggingMiddleware
{
//..
public async Task InvokeAsync(HttpContext context)
{
// 记录传入的请求路径
_logger.Log(LogLevel.Information, context.Request.Path);
// 调用管道中的下一个中间件
await _next(context);
// 获得唯一响应头
var uniqueResponseHeaders
= context.Response.Headers
.Select(x => x.Key)
.Distinct();
// 记录响应头名称
_logger.Log(LogLevel.Information, string.Join(", ", uniqueResponseHeaders));
}
}
}
将 LoggingMiddleware 添加到管道中
因为我更喜欢使用扩展方法来添加中间件到管道中,让我们创建一个新的扩展方法:
namespace ASPNET6Middleware.Extensions
{
public static class MiddlewareExtensions
{
//...
public static IApplicationBuilder UseLoggingMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<LoggingMiddleware>();
}
}
}
最后,我们需要在 Program.cs 中调用我们的新扩展方法,将LoggingMiddleware类添加到管道中:
app.UseLoggingMiddleware();
当我们运行应用程序时,我们可以看到代码(通过断点)可以正确地记录请求路径和响应头。

在本系列的下一篇文章中,我们将讲述中间件的执行顺序,展示一个记录执行时间的新中间件,并讨论在创建中间件管道时可能发生的一些常见问题。
版权声明
本文为[dotNET跨平台]所创,转载请带上原文链接,感谢
https://blog.csdn.net/sd7o95o/article/details/124287008
边栏推荐
- Deep q-network (dqn)
- Numpy stack function
- Linux redis - redis ha sentinel cluster construction details & redis master-slave deployment
- Opencv combines multiple pictures into video
- B blocks of the 46th ICPC Asian regional competition (Kunming)
- Kubernetes - detailed explanation of pod
- Difference between relative path and absolute path (often asked in interview)
- 《信息系统项目管理师总结》第五章 项目质量管理
- 树莓派开发笔记(十二):入手研华ADVANTECH工控树莓派UNO-220套件(一):介绍和运行系统
- Liunx foundation - zabbix5 0 monitoring system installation and deployment
猜你喜欢

Detailed explanation of distributed things

Golden nine silver ten interview season, you are welcome to take away the interview questions (with detailed answer analysis)

Solve the problem that PowerShell mining occupies 100% of cpu7 in win7

Opencv fills the rectangle with a transparent color

Summary of software test interview questions

Slave should be able to synchronize with the master in tests/integration/replication-psync.tcl

Linux Redis ——Redis HA Sentinel 集群搭建详解 & Redis主从部署

First knowledge of C language ~ branch statements
![[format] simple output (2)](/img/24/64739f5e6bbd54bfa9fb78b8c53c94.png)
[format] simple output (2)

Huawei machine test question -- deformation of hj53 Yang Hui triangle
随机推荐
【工欲善其事必先利其器】论文编辑及文献管理(Endnote,Latex,JabRef ,overleaf)资源下载及使用指南
Wepy learning record
Service avalanche effect
Domestic lightweight Kanban scrum agile project management tool
Planning code ROS migration POMDP prediction planning (I)
The usage of case when and select case when is very easy to use
JS relearning
最通俗易懂的依赖注入与控制反转
Blazor University (12)组件 — 组件生命周期
最通俗易懂的依赖注入之生命周期
Linux redis - redis database caching service
Windows MySQL 8 zip installation
《信息系统项目管理师总结》第六章 项目人力资源管理
ele之Table表格的封装
Difference between relative path and absolute path (often asked in interview)
Gavl021, gavl281, AC220V to 5v200ma small volume non isolated chip scheme
对.NET未来的一点感悟
Close the computer port
Summary of interface automation interview questions for software testing
Résumé du gestionnaire de projet du système d'information Chapitre VI gestion des ressources humaines du projet