聊聊 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)方法还可以定义其他参数,其他参数会通过依赖注入自动赋值。

相关推荐
Envyᥫᩣ2 小时前
C#语言:从入门到精通
开发语言·c#
IT技术分享社区8 小时前
C#实战:使用腾讯云识别服务轻松提取火车票信息
开发语言·c#·云计算·腾讯云·共识算法
△曉風殘月〆14 小时前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm
逐·風16 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
m0_6569747419 小时前
C#中的集合类及其使用
开发语言·c#
九鼎科技-Leo20 小时前
了解 .NET 运行时与 .NET 框架:基础概念与相互关系
windows·c#·.net
九鼎科技-Leo1 天前
什么是 ASP.NET Core?与 ASP.NET MVC 有什么区别?
windows·后端·c#·asp.net·mvc·.net
.net开发1 天前
WPF怎么通过RestSharp向后端发请求
前端·c#·.net·wpf
小乖兽技术1 天前
C#与C++交互开发系列(二十):跨进程通信之共享内存(Shared Memory)
c++·c#·交互·ipc
幼儿园园霸柒柒1 天前
第七章: 7.3求一个3*3的整型矩阵对角线元素之和
c语言·c++·算法·矩阵·c#·1024程序员节