示例源码:https://download.csdn.net/download/hefeng_aspnet/89998881
这是一篇关于如何在 .NET 6.0 中实现全局异常处理程序的快速文章。
全局错误处理程序用于捕获所有异常,并且无需在每个 .NET 应用程序中创建多个处理代码。
在此示例中,我们将使用中间件 和Serilog来集中日志收集的捕获和目标配置。
先决条件
Visual Studio 2022 (.NET 6.0)
Nuget包Serilog.AspNetCore,Serilog.Enrichers.Environment和Serilog.Exceptions
中间件
中间件基本上是 定义 HTTP 调用执行管道的组件,即请求在应用程序内执行的所有步骤,从请求到响应。它们是链接在一起的,因此一个中间件可以通过传递相同请求上下文的委托来执行另一个中间件。
需要创建的第一个中间件是ErrorHandlingMiddleware,负责捕获应用程序中的所有(未处理的)错误:
ErrorHandlingMiddleware.cs :
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
Log.Error(exception, "Erro na aplicação");
var code = HttpStatusCode.InternalServerError;
if (exception is Exception) code = HttpStatusCode.BadRequest;
// else if (exception is MyUnauthorizedException) code = HttpStatusCode.Unauthorized;
// else if (exception is MyException) code = HttpStatusCode.BadRequest;
var result = JsonConvert.SerializeObject(new { error = exception.Message });
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)code;
return context.Response.WriteAsync(result);
}
}
第二个中间件(RequestSerilLogMiddleware)将用于捕获附加信息,例如:认证用户的电子邮件、用户IP和标头信息。
RequestSerilLogMiddleware.cs:
public class RequestSerilLogMiddleware
{
private readonly RequestDelegate _next;
public RequestSerilLogMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
using (LogContext.PushProperty("UserName", context?.User?.Identity?.Name ?? "anônimo"))
using (LogContext.PushProperty("CorrelationId", GetCorrelationId(context)))
{
return _next.Invoke(context);
}
}
}
接下来需要配置Serilog,通知主要丰富日志记录添加更多信息:
SerilogExtensions.cs:
public static class SerilogExtensions
{
public static void AddSerilogApi(IConfiguration configuration)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.WithProperty("ApplicationName", $"API Exceptions - {Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT")}")
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithEnvironmentUserName()
.Enrich.WithExceptionDetails()
.WriteTo.Console()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}")
.CreateLogger();
}
}
最后,在program.cs类中,需要注册创建的两个中间件的使用:
program.cs:
var builder = WebApplication.CreateBuilder(args);
SerilogExtensions.AddSerilogApi(builder.Configuration);
builder.Host.UseSerilog(Log.Logger);
builder.Services.AddRouting(options => options.LowercaseUrls = true);
builder.Services.AddSwaggerApi(builder.Configuration);
builder.Services.AddControllers();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMiddleware<RequestSerilLogMiddleware>();
app.UseMiddleware<ErrorHandlingMiddleware>();
app.UseSwaggerDocApi();
app.UseHttpsRedirection();
app.UseRouting();
app.MapControllers();
app.Run();
测试
运行 API 时,可以通过调用/api/log/exception端点来测试错误收集,这会在应用程序控制器中引发错误并被ErrorHandlingMiddleware 中间件捕获:
捕获异常是所有应用程序的关键部分,使用中间件除了作为收集日志、自定义返回消息和获取用户的集中位置之外,也是让您的应用程序不因缺乏错误处理而“解除武装”的最安全方法凭证信息。
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。