1. 程式人生 > 實用技巧 >.Net Core2.2異常處理

.Net Core2.2異常處理

初始化新的專案,在Configure的第一行可以看到如下程式碼:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

程式碼使用 IsDevelopment() 判斷了當前是否為開發者模式,然後通過UseDeveloperExceptionPage() 就跳轉到了堆疊錯誤頁面。當然,正式環境的時候可不能這樣,所以用UseExceptionHandler() 這個預設錯誤處理方法,跳轉到了錯誤提示頁面,UseExceptionHandler() 還有一個過載方法使用lambda 表示式來處理異常:

app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        context.Response.StatusCode = 500;
        context.Response.ContentType = "text/html";
        await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");
        await context.Response.WriteAsync("
ERROR!<br><br>\r\n"); }); });

一、異常過濾器

建立我們自己的異常過濾器需要繼承IAsyncExceptionFilter ,然後實現 OnExceptionAsync 方法對錯誤資訊進行處理:

public class MyCustomerExceptionFilter : IAsyncExceptionFilter
{
    public Task OnExceptionAsync(ExceptionContext context)
    {
        if (context.ExceptionHandled == false
) { string msg = context.Exception.Message; context.Result = new ContentResult { Content = msg, StatusCode = StatusCodes.Status200OK, ContentType = "text/html;charset=utf-8" }; } context.ExceptionHandled = true; //異常已處理了 return Task.CompletedTask; } }

這裡將 context.ExceptionHandled 設定為了true,表示該異常已經被處理,後續的異常處理的中介軟體也不會再重複處理這個異常了。最後在 Startup.cs 中加入它就可以看:

services.AddControllers(options => options.Filters.Add(new MyCustomerExceptionFilter()));

二、異常中介軟體

異常中介軟體和異常過濾器的區別就是,異常中介軟體的範圍更廣,異常過濾器只能處理mvc中發生的錯誤,而中介軟體可以捕獲其之後的所有異常。如下:

public class MyExceptionMiddleware
{
    private readonly RequestDelegate _next;
    public MyExceptionMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public async Task Invoke(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception ex)
        {
            httpContext.Response.ContentType = "application/problem+json";

            var title = "An error occured: " + ex.Message;
            var details = ex.ToString();

            var problem = new ProblemDetails
            {
                Status = 200,
                Title = title,
                Detail = details
            };

            //Serialize the problem details object to the Response as JSON (using System.Text.Json)
            var stream = httpContext.Response.Body;
            await JsonSerializer.SerializeAsync(stream, problem);
        }
    }
}
app.UseMiddleware<MyExceptionMiddleware>();

不過這樣也沒啥必要,因為UseExceptionHandler 的過載方法也可以實現,最開始的時候已經給出了。