IAsyncExceptionFilter
在 ASP.NET Core 中,可以使用异常过滤器(Exception Filter)来捕获和处理应用程序中的异常。IExceptionFilter 接口和 IAsyncExceptionFilter 接口都可以用来实现自定义的异常过滤器。不过我更建议您考虑它的异步版本:IAsyncExceptionFilter。
public class CustomExceptionFilter : IAsyncExceptionFilter
{
private readonly ILogger<CustomExceptionFilter> _logger;
public CustomExceptionFilter(ILogger<CustomExceptionFilter> logger)
{
_logger = logger;
}
public async Task OnExceptionAsync(ExceptionContext context)
{
_logger.LogError(context.Exception, "An error occurred.");
if (!context.ExceptionHandled)
{
context.Result = new ViewResult { ViewName = "Error" };
context.ExceptionHandled = true;
}
await Task.CompletedTask;
}
}
在这个示例中,我们创建了一个名为 CustomExceptionFilter 的自定义异常过滤器,它实现了 IAsyncExceptionFilter 接口。在 OnExceptionAsync 方法中,我们记录了异常并返回一个 ViewResult 对象来显示用户友好的错误信息。
要使用这个过滤器,只需要在 Startup.ConfigureServices 方法中注册它:
services.AddMvc(options =>
{
options.Filters.Add<CustomExceptionFilter>();
});
中间件处理异常
新建一个中间件在管道中实现全局异常捕获。
public class MyExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<MyExceptionMiddleware> _logger;
public MyExceptionMiddleware(RequestDelegate next, ILogger<MyExceptionMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError($"An exception occurred: {ex}");
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var jsonResponse = System.Text.Json.JsonSerializer.Serialize(new { error = ex.Message });
await context.Response.WriteAsync(jsonResponse);
}
}
}
然后在 Startup.cs 中,注册管道:
app.UseMiddleware<MyExceptionMiddleware>();
默认的AspNet Core异常处理
if (env.IsDevelopment())
{
// dev环境,一旦报错就会跳转到错误堆栈页面
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "DaXiong.Demo.WebApi v1"));
}
else
{
// 非dev环境输出格式,个人根据实际情况扩展
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
Console.WriteLine();
// 处理异常并生成响应
var exception = context.Features.Get<IExceptionHandlerPathFeature>().Error;
var statusCode = (int)HttpStatusCode.InternalServerError;
var message = "An error occurred while processing your request.";
// 根据异常类型决定如何响应请求...
// 生成响应
context.Response.StatusCode = statusCode;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonConvert.SerializeObject(new
{
statusCode,
message
}));
});
});
}
注意中间件的运行顺序
后添加的中间件返回数据会覆盖,前面的
一般情况使用默认的错误处理中间件也够了
有了异常中间件还需要异常过滤器(IExceptionFilter )吗
IExceptionFilter 作为MVC中间件之间的内容,它需要MVC在发现错误之后将错误信息提交给它处理,因此它的错误处理范围仅限于MVC中间件。所以,假如我们需要捕获MVC中间件之前的一些错误,其实是捕获不到的。 而对于ExceptionHandlerMiddleware中间件来说就很简单了,它作为第一个中间件,凡是在它之后的所有错误它都能够捕获得到。
但是,如果你想要在一个控制器或动作方法上执行特定的异常处理逻辑,仍然可以使用 IAsyncExceptionFilter。通过使用该接口,你可以在控制器或动作方法级别组织、记录和响应异常。在这种情况下,控制器或动作方法将优先于全局的 UseExceptionHandler 中间件。