聊聊 ASP.NET Core 中间件(三):如何创建自己的中间件?

前言

本质上,中间件类也是一个普通的 .NET 类,它不需要继承任何父类或者实现任何接口。

但是有几个约定:

  1. 需要有一个构造方法
  2. 构造方法至少要有一个 RequestDelegate 类型的参数,用来指向下一个中间件。
  3. 需要定义一个名字为 Invoke 或 InvokeAsync 的方法
  4. 此方法中至少有一个 HttpContext 类型的参数
  5. 此个方法的返回值必须是 Task 类型

只要遵守以上这些约定,就可以轻松创建自己的中间件。

以下是一个 Step By Step 例子。

Step By Step 步骤

  1. 创建一个空 ASP.NET Core webapi 项目

  2. 定义一个用于中间件的实体类

    c# 复制代码
    public class CheckAndParsingMiddlewareModel
    {
    	public int i { get; set; }
    	public int j { get; set; }
    }
  3. 定义一个中间件类 CheckAndParsingMiddleware,留意注释

    c# 复制代码
    using System.Text.Json;
    using System.Text;
    
    /// <summary>
    /// 自定义中间类,要求如注释的 1~5 点
    /// </summary>
    public class CheckAndParsingMiddleware
    {
    	private readonly RequestDelegate next;
    
    	// 1. 需要有一个构造方法
    	// 2. 构造方法需要有一个 RequestDelegate 类型的参数,用于指向下一个中间件
    	public CheckAndParsingMiddleware(RequestDelegate next)
    	{
    		this.next = next;
    	}
    
    	// 3. 需要有一个名为 Invoke 或 InvokeAsync 的方法
    	// 4. 此方法至少要有一个 HttpContext 类型参数
    	// 5. 此方法的返回值必须是 Task 类型
    	public async Task InvokeAsync(HttpContext context)
    	{
    		string pwd = context.Request.Query["password"];
    		if (pwd == "123")
    		{
    			if (context.Request.HasJsonContentType())
    			{
    				// 解析 Body 参数的值
    				var reqStream = context.Request.BodyReader.AsStream();
    				var jsonObj = JsonSerializer.Deserialize<CheckAndParsingMiddlewareModel>(reqStream);
    
    				// 将数据存在Items中
    				// HttpContext.Items 在同一个请求中是共享的,可以用它在多个中间件之间来传递数据
    				context.Items["BodyJson"] = jsonObj; 
    			}
    			// 把请求转给下一个中间件
    			await next(context); 
    		}
    		else
    		{
    			context.Response.StatusCode = 401;
    		}
    	}
    }
  4. 打开 Program.cs,编写使用自定义的中间件的代码,如:

    c# 复制代码
    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    
    app.Map("/testForCustomMiddleware", async appbuild => { 
    	// 使用自定义的中间件
    	appbuild.UseMiddleware<CheckAndParsingMiddleware>();
    	
    	// 执行
    	appbuild.Run(async ctx => {
    		ctx.Response.ContentType = "text/html";
    		ctx.Response.StatusCode = 200;
    		var jsonObj = (CheckAndParsingMiddlewareModel)ctx.Items["BodyJson"];
    		int i = jsonObj.i;
    		int j = jsonObj.j;
    		await ctx.Response.WriteAsync($"{i}+{j}={i+j}");
    	});
    });
    
    app.Run();
  5. 其它:解析 Body 参数值的方法

    c# 复制代码
    // 方法 1
    var reqStream = context.Request.BodyReader.AsStream();
    var jsonObj = JsonSerializer.Deserialize<CheckAndParsingMiddlewareModel>(reqStream);
    
    // 方法 2
    Stream reqStream = context.Request.Body;
    byte[] buffer = new byte[context.Request.ContentLength!.Value];
    await reqStream.ReadAsync(buffer, 0, buffer.Length);
    var reqStr = Encoding.UTF8.GetString(buffer);
    dynamic jsonObj = JsonSerializer.Deserialize<dynamic>(reqStr)!;

扩展

中间件类的构造方法和 Invoke(或 InvokeAsync)方法还可以定义其他参数,其他参数会通过依赖注入自动赋值。

相关推荐
缺点内向9 分钟前
如何在 C# .NET 中将 Markdown 转换为 PDF 和 Excel:完整指南
pdf·c#·.net·excel
CodeCraft Studio12 分钟前
Excel处理控件Aspose.Cells教程:使用C#在Excel中创建旭日图
c#·excel·aspose·excel旭日图·excel库·excel开发控件·excel api库
民乐团扒谱机17 分钟前
【微实验】仿AU音频编辑器开发实践:从零构建音频可视化工具
算法·c#·仿真·audio·fft·频谱
武藤一雄1 小时前
彻底吃透.NET中序列化反序列化
xml·微软·c#·json·.net·.netcore
one9962 小时前
C# 的进程间通信(IPC,Inter-Process Communication)
开发语言·c#
CreasyChan2 小时前
unity-向量数学:由浅入深详解
unity·c#
专注VB编程开发20年12 小时前
C#全面超越JAVA,主要还是跨平台用的人少
java·c#·.net·跨平台
小猪快跑爱摄影15 小时前
【AutoCad 2025】【C#】零基础教程(四)——MText 常见属性
c#·autocad
炼钢厂17 小时前
C#6——DateTime
c#
Lv117700818 小时前
Visual Studio中的多态
ide·笔记·c#·visual studio