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 中間件。