- Published on
ASP.NET Core 使用內建的 ExceptionHandler Middleware 實作全站 Exception 處理
要實作全站的 Exception Handler 的話,內建的 Middleware
有一個 UseExceptionHandler
可以使用,而且可以在 ExceptionHandlerOptions
裡面寫我們需要 Handler 的邏輯
實作 UseExceptionHandler
- 在
Configure
裡面會有執行先後次序的問題,如果是UseExceptionHandler
的話,建議放在最前面,這樣子才有辦法抓到後面 Middleware 的 exception
public void Configure(IApplicationBuilder app, ILogger logger)
{
app.UseExceptionHandler(new ExceptionHandlerOptions());
app.UseMvc(routes =>
{
routes.MapRoute(name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
ExceptionHandlerOptions
裡面只有兩個東西- 一個是
ExceptionHandlingPath
也就是出錯了要導到什麼路徑叫它處理 - 一個是
ExceptionHandler
,就是如何處理 Exception
- 一個是
我們可以從
Features
拿到IExceptionHandlerFeature
,這裡面有 Error 可以使用 (也就是補抓到的Exception
),我們可以判斷如果它不是空的話,就寫一筆 Log,然後返回狀態碼500
和和自定的內容
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseExceptionHandler(new ExceptionHandlerOptions
{
ExceptionHandler = async context =>
{
var exceptionFeature = context.Features.Get<IExceptionHandlerFeature>();
if (exceptionFeature?.Error != null)
{
var logger = loggerFactory.CreateLogger("ExceptionHandler");
logger.LogError(exceptionFeature.Error, exceptionFeature.Error.Message);
}
context.Response.StatusCode = 500;
var result = JsonConvert.SerializeObject(new { Result = "Error" });
await context.Response.WriteAsync(result);
}
});
}
測試
- 在某個 Action 裡面直接 throw Exception
- 實際執行 Action,可以看到畫面上返回的是我們自定義的內容
- 然後 Status Code 是
500
- Log 也有寫到 Console
寫成 Extension
- 為了方便使用,我們可以把 UseExceptionHandler 的程式碼搬到 Extension 裡面
public static class MiddlewareExtension
{
public static void UseExceptionHandler(this IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseExceptionHandler(new ExceptionHandlerOptions
{
ExceptionHandler = async context =>
{
var exceptionFeature = context.Features.Get<IExceptionHandlerFeature>();
if (exceptionFeature?.Error != null)
{
var logger = loggerFactory.CreateLogger("ExceptionHandler");
logger.LogError(exceptionFeature.Error, exceptionFeature.Error.Message);
}
context.Response.StatusCode = 500;
var result = JsonConvert.SerializeObject(new { Result = "Error" });
await context.Response.WriteAsync(result);
}
});
}
}
- 在使用的時候一行就可以解決了
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseExceptionHandler(loggerFactory);
}