當API被呼叫且發生例外時,不太會希望預設的錯誤訊息被傳回給使用者,在C#中可以使用try catch攔截錯誤訊息。
但在每個可能會發生錯誤的地方都加上try catch相當繁瑣,使用Middleware可以捕捉錯誤訊息,並在返回給使用者之前統一處理,不僅可以節省開發時間,還能將錯誤訊息攔截,避免洩漏過多內部訊息給使用者,提高安全性。
環境
- macOS Ventura 13.0(Apple M1 Pro)
- .NET 6.0
- Visual Studio Community 2022 for Mac 17.6.1
Middleware簡介
ASP.NET Core中定義的Middleware可以用來處理所有的HTTP Request和Response,他們會一個串著一個,像一個管線(Pipeline)。
每個Middleware可以決定是否要進入下一個Middleware,若沒有呼叫next()則不會進入下一個Middleware。
由於所有的請求都會經過所有的Middleware,想要在例外發生時有一個地方可以捕捉所有例外,Middleware再適合不過了。
實作Middleware
在專案中新增一個Middlewares
資料夾,統一存放自定義的Middlewares。
接著在資料夾中新增檔名為ExceptionHandleMiddleware.cs
的類別,在類別中加入下列程式碼:
public class ExceptionHandleMiddleware
{
private readonly RequestDelegate _next;
public ExceptionHandleMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
//執行下一步
await _next(context);
}
catch (Exception exception)
{
//當錯誤發生時呼叫 HandleExceptionAsync 方法,不執行下一個Middleware
await HandleExceptionAsync(context, exception);
}
}
//直接返回 InternalServerError 給使用者
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
return context.Response.WriteAsync($"{context.Response.StatusCode} Internal Server Error.");
}
}
Middleware完成後依照Program.cs的形式將Middleware使用IApplicationBuilder包起來,在Middlewares資料夾中新增名稱為ExceptionHandleMiddlewareExtensions.cs
的類別,檔案內容如下:
public static class ExceptionHandleMiddlewareExtensions
{
public static IApplicationBuilder UseExceptionHandleMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<ExceptionHandleMiddleware>();
}
}
接著在Program.cs
中加入app.UseExceptionHandleMiddleware();
即可完成自訂Middleware的設定。
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
...
var app = builder.Build();
...
app.UseExceptionHandleMiddleware();//加入這行即可完成設定
...
app.Run();
}
}