【Asp.Net.Core】【middleWare】

373 阅读2分钟

middleWare是在应用在流水线式处理请求和响应中的一个组件(类似Filter/Interceptor的作用),存在的目的就是为了单独执行不同的功能,例如一个middleware执行重定向,一个Middleware执行身份验证:

image.png

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

//app.Run 不会把请求发送给另一个middleWare,一般用于最后一个middleware
app.Run(async (HttpContext context) =>
{
    await context.Response.WriteAsync("Hello");
});

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

app.Run();

但是hello again并不会显示,也就是说app.Run()一般用于终结middleWare的使用。 如何将多个middleWare chain到一起呢?

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

//middleware 1
app.Use(async (HttpContext context,RequestDelegate next) =>
{
    await context.Response.WriteAsync("Hello");
    await next(context);
});

//middleware 2
app.Use(async (HttpContext context, RequestDelegate next) =>
{
    await context.Response.WriteAsync("Hello again");
    await next(context);
});
//middleware 3
app.Run(async (HttpContext context) =>
{
    await context.Response.WriteAsync("Hello the third time");
   
});

app.Run();

image.png

继承IMiddleware

如果middleware要执行很多代码,应该把单独功能写成一个类,单独分离出一个文件:

image.png

  1. 新建文件夹和类

image.png 2. 继承 IMiddleware接口——右键,快速操作与重构

namespace MiddlewareExample.CustomMiddleware
{
    public class MyCustomMiddleware : IMiddleware
    {
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            await context.Response.WriteAsync("My Custom Middleware - Starts");
            await next(context);
            await context.Response.WriteAsync("My Custom Middleware - Ends");
        }
    }
}

  1. 使用——加入Services服务
using MiddlewareExample.CustomMiddleware;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTransient<MyCustomMiddleware>();
var app = builder.Build();

//middleware 1
app.Use(async (HttpContext context,RequestDelegate next) =>
{
    await context.Response.WriteAsync("Hello");
    await next(context);
});

//middleware 2
app.UseMiddleware<MyCustomMiddleware>();
//middleware 3
app.Run(async (HttpContext context) =>
{
    await context.Response.WriteAsync("Hello the third time");
   
});

app.Run();

如何化简自定义的middleware?

  1. 新建一个类
public static class CustomMiddlewareExtension
{
    public static IApplicationBuilder UseMyCustomMiddleware(this IApplicationBuilder app)
    {
        return app.UseMiddleware<MyCustomMiddleware>();
    }
}

2.使用

app.UseMyCustomMiddleware();

不继承IMiddleware实现

image.png

  1. 新建中间项类 image.png
  2. 实现
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

namespace MiddlewareExample.CustomMiddleware
{
    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class HelloMiddleware
    {
        private readonly RequestDelegate _next;

        public HelloMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            //before logic
            if(httpContext.Request.Query.ContainsKey("firstname") &&
                httpContext.Request.Query.ContainsKey("lastname"))
            {
                string fullName = httpContext.Request.Query["firstname"]
                    + " " + httpContext.Request.Query["lastname"];
                await httpContext.Response.WriteAsync(fullName);
            }
            await _next(httpContext);
            //after logic
        }
    }

    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class MiddlewareExtensions
    {
        public static IApplicationBuilder UseHelloMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<HelloMiddleware>();
        }
    }
}

3.使用

app.UseHelloMiddleware();

Middleware 正确的顺序

image.png

image.png

UseWhen

image.png

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseWhen(
    context => context.Request.Query.ContainsKey("username"),
    app => {
        app.Use(async (context, next) =>
        {
            await context.Response.WriteAsync("Hello from " +
                "Middleware branch\n");
            await next();
        });
    });

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from middleware " +
        "at main chain");
});
app.Run();

image.png

image.png