天天看點

Dotnet Core異常處理的優雅實踐

異常處理,也可以做得很優雅。

一、前言

異常處理的重要性,老司機都清楚。

這篇文章,我們來理一下Dotnet Core異常處理的幾種方式。

  1. Try Catch方式
  2. Exception Filter方式
  3. 内建的異常進行中間件
  4. 自定義的異常進行中間件

這是目前使用比較多的幾種方式。其中,第1、2種其實算是一種,是C#兩個語言版本的東西。

    為了防止不提供原網址的轉載,特在這裡加上原文連結:https://www.cnblogs.com/tiger-wang/p/13562817.html

二、Try Catch方式

這是最通常使用的一種方式。

看例子:

[HttpGet]
public IActionResult Get()
{
    try
    {
        List<string> example_list = null;
        var item_count  = example_list.Count();
        return Ok(item_count);
    }
    catch (Exception ex)
    {
        return StatusCode(HttpContext.Response.StatusCode, ex.Message);
    }
}
           

有時候,我們可能需要處理多種異常。

catch (Exception ex)
{
    if(ex.InnerException == null)
        return StatusCode(HttpContext.Response.StatusCode, "error");
    else
        return StatusCode(HttpContext.Response.StatusCode, "other error");
}
           

在C# 6以後,Try Catch加了一個過濾

Exception Filter

文法,可以在

catch

後跟一個條件語句。上面這個

catch

可以寫為:

catch (Exception ex) when (ex.InnerException == null)
{
    return StatusCode(HttpContext.Response.StatusCode, "error");
}
catch (Exception ex)
{
    return StatusCode(HttpContext.Response.StatusCode, "other error");
}
           

在這個文法中,

when

後面是一個

bool

的判斷,為

true

則進入

catch

塊,為

false

則跳過。

在C#中,異常是從内向外逐層查找處理程式的,随着查找層數的增加,性能會逐漸降低。

概念上,

try

塊的運作效率和不加

try

塊的性能差不多,可以認為基本一緻;但

catch

塊的性能會差很多。是以一般來說,一個基本的原則是,不要把

try

catch

作為程式的邏輯。

但是,如果我們需要又需要記錄這個異常,該怎麼辦?

這時候,就可以利用

Exception Filter

文法。

看代碼:

[HttpGet]
public IActionResult Get()
{
    try
    {
        List<string> example_list = null;
        var item_count = example_list.Count();
        return Ok(item_count);
    }
    catch (Exception ex) when (log(ex))
    {
    }
    return StatusCode(HttpContext.Response.StatusCode, "error");
}

private bool log(Exception ex)
{
    Debug.Print(ex.Message);
    return false;
}
           

在這個代碼中,

when

條件後跟了一個傳回

bool

的方法。我們可以在這個方法中進行異常的記錄處理,然後傳回

false

為什麼要傳回

false

呢?是因為我們要記錄異常,但為了性能的考慮,不希望代碼進入到

catch

塊。傳回

false

後,程式執行了

log

方法,卻又沒進入到

catch

塊。

當然,如果你想進入到

catch

塊,那傳回

true

就可以了。

嗯。這一段能看明白就行了,這不算是一個正常的解決辦法,隻能算一個旁門的小技巧。

三、内建的異常中間件

内建的異常處理,有兩個。

一個是我們最常見的,在建立

webapi

類型的工程時,

Startup.cs

檔案中已經預設生成好的:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
}
           

這個

app.UseDeveloperExceptionPage

就是架構中用于顯示異常的詳細資訊的中間件。

另一個,是

app.UseExceptionHandler

,也是一個内置的用來處理異常的中間件,可以這樣用:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseExceptionHandler(para...);
}
           

參數可以是一個

Endpoint

,也可以是一個

Action

。實際應用時,還可以寫成一個

IApplicationBuilder

的擴充。

四、自定義的中間件

如果對異常管理有很高的要求,自定義異常進行中間件,是最合适的一種方式。

中間件的寫法,我在前文一文說通Dotnet Core的中間件中有詳細的說明,這兒不再多說。

給一段例子看看:

public class CustomExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<CustomExceptionMiddleware> _logger;
    public CustomExceptionMiddleware(RequestDelegate next, ILogger<CustomExceptionMiddleware> logger)
    {
        _logger = logger;
        _next = next;
    }
    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception ex)
        {
            _logger.LogError($"Exception occur: {ex}");
            await HandleExceptionAsync(httpContext, ex);
        }
    }
    private Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        return context.Response.WriteAsync(new CustomError()
        {
            StatusCode = context.Response.StatusCode,
            Message = "custom middleware error."
        }.ToString());
    }
}
           

使用時,就在

Configure

裡引入即可。

(全文完)

本文的代碼已上傳到Github,位置在:https://github.com/humornif/Demo-Code/tree/master/0023/demo/demo

Dotnet Core異常處理的優雅實踐

微信公衆号:老王Plus

掃描二維碼,關注個人公衆号,可以第一時間得到最新的個人文章和内容推送

本文版權歸作者所有,轉載請保留此聲明和原文連結

繼續閱讀