.NET 6版本中间件的使用
.NET 6版本中间件的使用
中间件是一种处理HTTP请求和响应的可重用组件,通常用于添加处理逻辑或修改请求和响应。本文将演示如何创建.NET 6版本的中间件。
创建中间件
让我们从创建一个简单的中间件类开始。我们将打印请求的URL,然后调用下一个中间件:
public class MyMiddleware
{
private readonly RequestDelegate _next;
public MyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
Console.WriteLine($"[MyMiddleware] URL: {context.Request.Path}");
await _next(context);
}
}
在上面的代码中,我们定义了一个MyMiddleware
类,它实现了InvokeAsync
方法。在这个方法中,我们打印了请求的URL,并调用下一个中间件。
注册中间件
在.NET 6中,注册中间件的方式也类似于.NET 5。我们可以将我们的中间件添加到应用程序的请求处理管道中。
builder.UseMiddleware<MyMiddleware>();
请注意,上面的代码应该在app.UseRouting()
之后调用,但在app.UseEndpoints()
之前。
完整的Program.cs
文件如下所示:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseMiddleware<MyMiddleware>();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.Run();
在上面的代码中,我们将MyMiddleware
添加到了请求处理管道中。然后我们添加了一些其他的中间件,例如HTTPS重定向和静态文件服务。
测试中间件
现在我们已经完成了自己的中间件,我们来测试它。
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
...
})
.ToArray();
}
}
上面的代码中,我们创建了一个简单的WeatherForecastController
,其中有一个Get()
操作。我们将在这个操作中测试我们的中间件。
通过调用Swagger UI来测试应用程序:
- 在浏览器中导航到
https://{your_host}/swagger/index.html
。 - 选择“GET WeatherForecast”操作,然后单击“Try it out”按钮。
- 单击“Execute”按钮。
您应该看到控制台输出我们的自定义中间件的URL:
[MyMiddleware] URL: /WeatherForecast
中间件的顺序
在注册多个中间件时,它们的顺序非常重要。请求将从第一个中间件开始处理,然后逐个传递到下一个中间件,直到到达最后一个中间件,然后响应将根据这些中间件的顺序返回。在.NET 6中,您可以通过调用 UseMiddleware<T>
或 UseMiddleware
方法添加多个中间件。
例如,让我们创建一个新的中间件类,以便我们可以测试中间件的顺序:
public class MySecondMiddleware
{
private readonly RequestDelegate _next;
public MySecondMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
Console.WriteLine("[MySecondMiddleware] Start");
await _next(context);
Console.WriteLine("[MySecondMiddleware] End");
}
}
在上面的代码中,我们定义了一个名为MySecondMiddleware
的新中间件类,它与MyMiddleware
类非常相似。它在请求处理管道的开头打印了消息,然后在请求处理管道的结尾打印了另一个消息。
现在,我们可以将两个中间件添加到应用程序中:
app.UseMiddleware<MyMiddleware>();
app.UseMiddleware<MySecondMiddleware>();
您应该注意到,我们添加了 MyMiddleware
和 MySecondMiddleware
中间件,它们的顺序是有意义的,因为它们将按照注册的顺序依次处理请求。
如果我们在测试控制器方法时,您会看到控制台输出,它显示请求和响应在两个中间件中传递。输出如下:
[MyMiddleware] URL: /WeatherForecast
[MySecondMiddleware] Start
[MySecondMiddleware] End
您可以看到,请求通过了 MyMiddleware
中间件,然后通过 MySecondMiddleware
中间件。注意消息的顺序是相反的,因为我们将它们注册成了相反的顺序。
控制中间件的流程
在.NET 6中,我们可以通过终止请求来控制中间件流程。如果我们需要在请求处理管道中停止中间件的处理过程,则可以使用 HttpContext.Abort()
方法。
例如,让我们为我们的控制器方法添加一些逻辑,并在中间件中检查该逻辑。如果条件不满足,我们将终止请求处理过程。
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpGet("{id}")]
public IActionResult Get(int id)
{
if (id < 1 || id > 5)
{
return BadRequest("Invalid ID");
}
return Ok(Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
...
}).ToArray());
}
}
在上面的代码中,我们更改了 Get()
操作以检查传递的 id
值。如果 id
不在1到5的范围内,则返回400响应。
现在,让我们在 MyMiddleware
中间件中添加一些逻辑,以检查请求是否是有效请求。
public class MyMiddleware
{
private readonly RequestDelegate _next;
public MyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
Console.WriteLine($"[MyMiddleware] URL: {context.Request.Path}");
if (context.Request.Path == "/WeatherForecast/2")
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
await context.Response.WriteAsync("Resource not found");
return;
}
await _next(context);
}
}
在上面的代码中,我们添加了一个检查,如果URL是 /WeatherForecast/2
,则返回404响应并终止请求处理过程。
现在,当我们通过查找 /WeatherForecast/2
在浏览器中测试应用程序时,我们应该收到 Resource not found
响应。并且应用程序将在 MyMiddleware
中间件中止请求处理过程。
总结:
在本文中,我们演示了如何在.NET 6中创建和使用中间件,并介绍了如何控制中间件的顺序。中间件是.NET Web应用程序中非常有用的组件,它允许我们轻松地处理请求和响应。注意中间件的注册顺序是非常重要的,尤其是在使用多个中间件的情况下。我们还演示了如何将自定义逻辑添加到控制器方法中,并在中间件中检查该逻辑。中间件是.NET Web应用程序非常有用的组件,并且.NET 6为中间件的处理带来了更多的灵活性。