iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 15
0
Modern Web

我與 ASP.NET Core 的 30天系列 第 15

[Day15] 例外事件處理 - 我與 ASP.NET Core 3 的 30天

  • 分享至 

  • xImage
  •  

應用程式運行的過程中,不免會有例外事件的錯誤發生,透過良好的設計來處理例外狀況與錯誤,能防止應用程式因此崩潰壞掉,並能讓使用者也可以有比較良好的體驗。
今天就用ASP.NET Core Web API 作為處理和自訂錯誤處理的範例。

開發人員例外狀況頁面

在ASP.NET Core 3 應用程式的開發時期中提供了開發人員例外狀況頁面,這是一個非常實用的工具,可以取得例外狀況的詳細資訊與堆疊追蹤。它會使用 DeveloperExceptionPageMiddleware 從 HTTP pipeline捕獲同步和非同步例外狀況,並產生錯誤回應。
在APS.NET Core 專案範本中,都可以在Startup.Configure看到下列程式碼

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

在專案範本中,開發時期都會預設為我們啟用開發人員例外狀況頁面,以下示範在開發時期使用Postman呼叫Web API,所回傳的錯誤格式
https://ithelp.ithome.com.tw/upload/images/20200930/20129389c6kT3uLoMc.png
在一般的使用情況下,會收到純文字的錯誤堆疊(Stack)訊息。

只要在Request Headers中加入 Accept: text/html(如下圖所示),就可以看到完整的開發人員例外狀況頁面
https://ithelp.ithome.com.tw/upload/images/20200930/201293895WVY3djud0.png

透過HTML格式的回應讓錯誤訊息變得比較漂亮易閱讀。

自訂例外事件處理 Exeption Handler

在上面的範例中,如果是非開發環境下如果發生了例外事件,伺服器端就會直接報錯,而且不會回應任何資訊,如以下畫面
https://ithelp.ithome.com.tw/upload/images/20200930/20129389RN6seepPTw.png
伺服器只會報500錯誤,但是在相對更需要穩定的正式環境下,這樣的錯誤是非常難以處理的,這時候就需要對非開發環境作出不同的例外處理。

我們可以透過ExcetionHanlder的 Middleware pipeline來進行非開發環境的例外處理
首先要在Startup.Configure中作出以下改動

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/error");
}

透過UseExceptionHandler()將非開發環境的例外事件處理都引導至路由為 /error 的Action

接著建立一個ErrorController,並加入以下內容

[Route("api/[controller]")]
[ApiController]
public class ErrorController : ControllerBase
{
    [Route("/error")]
    public ActionResult Error() => Problem();
}

透過 [Route("/error")] 強制將Action的路由變成 /error
上述名為Error的Action會將RFC 7807格式的錯誤訊息回傳至用戶端
https://ithelp.ithome.com.tw/upload/images/20200930/20129389tNsUtsjMlX.png
這樣便能為不同的環境設置不同的錯誤處理機制。

補充:在MVC的專案範本中,提供了錯誤頁面可供非開發環境下使用。
MVC中的Startup.Configure

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

https://ithelp.ithome.com.tw/upload/images/20200930/201293896ufAxN520M.png

備註:env.IsDevelopment()是從Properties/launchSettings.json取得的組態設定,後面會為組態設定做進一步的介紹。

例外處理建議方式

上面的範例都是在介紹,當拋出錯誤的時候,應該如何顯示錯誤訊息,但是在一個穩定的應用程式中,不會什麼錯誤都直接拋出讓前端的使用者看到,因此針對例外處理的方式有幾點建議:

  • 使用try/catch/finaly來攔截可能發生的錯誤,讓例外狀況發生時,應用程式可以適當的處理錯誤或結束,保障應用程式的品質。
  • 攔截錯誤後,進行有效資訊的紀錄,以提供開發人員有效率的偵測與檢查問題。
  • 針對不同類型的例外事件進行攔截,不使用類似 System.Exception、System.SystemException 等非特定的例外狀況來處理錯誤。
  • 攔截例外狀況時,不要排除任何可能的特殊例外狀況
  • 請勿過度使用攔截, 應該經常允許例外狀況散佈到呼叫堆疊上。
  • 請使用 try-finally 並避免使用 try-catch 來清除程式碼。 在編寫完善的例外狀況程式碼中,try-finally 遠比 try-catch 更為常用。
  • 當攔截並重新擲回例外狀況時,最好使用空白擲回方式, 因為這是保留例外狀況呼叫堆疊的最好方式。
  • 請不要使用無參數的 catch 區塊來處理不符合 CLS 標準的例外狀況 (不是衍生自 System.Exception 的例外狀況)。 可支援不是衍生自 Exception 的例外狀況之語言可以自由處理那些不符合 CLS 標準的例外狀況。

參考資料
MSDN-例外處理
處理 ASP.NET Core 中的錯誤


上一篇
[Day14] Filters - 我與 ASP.NET Core 3 的 30天
下一篇
[Day16] Logging 記錄管理 - 我與 ASP.NET Core 3 的 30天
系列文
我與 ASP.NET Core 的 30天31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言