ASP.NET MVC 客製錯誤畫面實務 (ASP.NET MVC Custom Error Practice)
2022-08-20
介紹在 ASP.NET MVC 開發上,如何藉由設定 customErrors
以及 httpErrors
將應用程式運行過程的錯誤畫面進行客製,提升使用者體驗 😊
說明
良好的客製化錯誤頁面具備的特性:
- 在本機顯示具體的錯誤訊息
- 在遠距用戶端顯示客製化的錯誤訊息
- 不使用重導 (302),而是顯示錯誤的內容並搭配正確的 HTTP Status Code
圖解 ASP.NET MVC Custom Error
ASP.NET MVC 預設在 Filters 上已註冊 HandleError,因此預設上發生在 ASP.NET 的 Http Status Code 500 都會交由 HandleErrorAttribute 所處理。
若取消這個註冊,則會恢復到由 .NET Error (customErrors) 進行處理。此外如果在 HandleErrorAttribute 再度發生錯誤,也會交回由 .NET Error (customErrors) 進行處理。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
而如果 existingResponse 為 Replace,則所有由 .NET Error (customErrors) 負責的錯誤都會交由 IIS Error (httpErrors) 所負責!
造成錯誤的亂源:
- Route Error
- ASP.NET MVC 路由發生的錯誤,例如不存在的路由 /Home/a,由 ASP.NET 處理錯誤
- Throw New Exception
- 拋出例外,會引發 HttpStatusCode 500,由 ASP.NET 處理錯誤,預設會被 CustomError 處理
- Throw New Exception(404, message)
- 拋出例外,並且指定 HttpStatusCode 404,由 ASP.NET 處理錯誤,預設不會被 CustomError 處理
- HttpStatusCodeResult
- Controller 可以回應的 Result,可以動態選擇要回應的 Http Status Code,由 IIS 處理錯誤
- Http NotFound
- Controller 可以回應的 Result (相當於 HttpStatusCodeResult 404) 由 IIS 處理錯誤
- 1.jpg / 1.asp / 1.html
- 不存在的資源
- 1.aspx / 1.ashx / 1.asmx
- 不存在的 ASP.NET 負責解析的資源
httpErrors 是 IIS 7 以後出現的功能,因此要使用 Integration Pipeline 才能夠使用。
實戰 ASP.NET MVC 客製錯誤
這是預熱菜範例,隨時可以端上桌,加入到每個專案使用,或者是每一個新建立的專案都應該進行的設定。
為了兼具客製化錯誤頁面的良好特性,採用在專案中加入 Error Controller 的方式處理,並且整合 customErrors 與 httpErrors 的使用。
首先取消 FilterConfig.cs 的 HandleErrorAttribute 註冊。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
接著在 web.config 進行設定:
<system.web>
<customErrors mode="On" defaultRedirect="~/Error">
<error statusCode="404" redirect="~/Error/NotFound" />
</customErrors>
</system.web>
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath=""
path="/Error/NotFound" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
最後加入 Controller 以及相關的 View:
ErrorController.cs
public class ErrorController : Controller
{
// GET: Error
public ActionResult Index()
{
return View();
}
// GET: Error/NotFound
public ActionResult NotFound(){
Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.StatusDescription = "Not Found!";
return View();
}
// GET: Error/Gone
public ActionResult Gone()
{
Response.Status = "410 Gone";
Response.StatusCode = 410;
Response.StatusDescription = "Gone!";
return View("NotFound");
}
public ActionResult StatusCode(int statuscode)
{
return new HttpStatusCodeResult(statuscode);
}
public ActionResult HttpNotFoundAction()
{
return HttpNotFound();
}
[HandleError]
public ActionResult ThrowException()
{
throw new HttpException();
return View();
}
}
參考資料
HandleErrorAttribute.cs | GitHub
Yowkow's Notes 所分享的 httpErrors 與 customErrors 在 ASP.NET MVC 與 ASP.NET WEB API 中的處理方式
軟體主廚的程式料理廚房所分享的 個人常用的 ASP.NET MVC 自訂 HTTP 回應碼畫面的套路