middleWare是在应用在流水线式处理请求和响应中的一个组件(类似Filter/Interceptor的作用),存在的目的就是为了单独执行不同的功能,例如一个middleware执行重定向,一个Middleware执行身份验证:
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();
继承IMiddleware类
如果middleware要执行很多代码,应该把单独功能写成一个类,单独分离出一个文件:
- 新建文件夹和类
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");
}
}
}
- 使用——加入
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?
- 新建一个类
public static class CustomMiddlewareExtension
{
public static IApplicationBuilder UseMyCustomMiddleware(this IApplicationBuilder app)
{
return app.UseMiddleware<MyCustomMiddleware>();
}
}
2.使用
app.UseMyCustomMiddleware();
不继承IMiddleware实现
- 新建中间项类
- 实现
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 正确的顺序
UseWhen
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();