[ASP.NET MVC] Error Handling(3) – 全域性的 Error Handler

[ASP.NET MVC] Error Handling(3) – 全域性的 Error Handler

在第一篇文章裡,我們知道了怎麼在網站發生錯誤時,導向到我們自訂的 Error Page。
而在第二篇文章裡,則是介紹了怎麼在 Action 和 Controller 裡 Handling Error。

現在來看更高一級的層次:怎麼讓 HandleErrorAttribute 應用到整個網站?

只要定義全域性的 Error Handler 就行了。

在 /App_Start/FilterConfig.cs 裡,裡面會有一個 RegisterGlobalFilters() Method。
可以看到裡面已經有一行 filters.Add(new HandleErrorAttribute()); 。
這行是預設的,意思就是他會捕捉到所有 Error,如果你在第一篇文章裡,把這一行註解掉,那他無法捕捉 Error,最後就沒辦法顯示我們自訂的 Error Page。


接著我們把第二章的程式改寫在這邊。


public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
      filters.Add(new HandleErrorAttribute
      {
          ExceptionType = typeof(System.Data.DataException),
          View = "DatabaseError"
      });
      
      filters.Add(new HandleErrorAttribute());
}

這邊要注意的是,他執行的順序是由上而下的,當上面的 filter 無法捕捉錯誤 時,才會繼續往下執行,而因為我們無法定義所有的錯誤,所以我們並不會把它預設的那一行程式刪除,而是把我們的 filter 加在上面,這樣才能確保抓到所有的錯誤。


而你也可以手動指定它們執行的順序,只要加上第二個參數就行了。


public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
      filters.Add(new HandleErrorAttribute
      {
          ExceptionType = typeof(System.Data.DataException),
          View = "DatabaseError"
      }, 1);
      
      filters.Add(new HandleErrorAttribute(), 2);
}

上面雖然寫能抓到所有錯誤,但其實 HandleErrorAttribute 只能抓到 HTTP 500 系列的錯誤,如果像是 404 這種的就抓不到了,需要再另外定義。

現在我們把 web.config 的


<customErrors mode="On">
</customErrors>

改成


<customErrors mode="On" defaultRedirect="GenericErrorPage.htm">
   <error statusCode="404" redirect="~/error/notfound"></error>
</customErrors>

有兩個重點是

  1. 如果 web.config 有將 custom errors 設成 On,程式裡面也有使用 HandleErrorAttribute,那在發生錯誤時,程式會自動導向到 Error.cshtml。
    (它會在你當前頁面的資料夾裡尋找是否有 Error.cshtml ,如果找不到才會去 Views/Shared 裡面找)
    而忽略掉 customErrors 所設定的 defaultRedirect 跟裡面的 <error statusCode="404" redirect="~/error/notfound"></error>。
  2. 如果 web.config 有將 custom errors 設成 On,程式裡面沒有使用 HandleErrorAttribute,那在發生錯誤時,才會導向到 customErrors 所設定的 defaultRedirect 或裡面的 <error statusCode="404" redirect="~/error/notfound"></error>。

那如果要測試第二點,是不是要把 HandleErrorAttribute 的程式全刪掉?
當然不用那麼麻煩,只要把 Global.asax.cs 裡面的 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 註解掉就行了。

至此,我們已經看完 ASP.NET MVC 內建的 Error Handling。