文章目錄
httpErrors 與 customErrors 在 ASP.NET MVC 與 ASP.NET WEB API 中的處理方式
這是同事遇到的 production issue,大意是設定了 customErrors 後出現 cpu 釘死在 100% 的重大缺失,聽到這樣的描述立馬想到可以藉機練習黑大最近幾篇文章提到的幾個 debug 工具,但為時已晚 事發在多日前,加上同事已定位實際造成問題的設定,只好期待下次機會,開開玩笑,production issue 還是不要有的好
問題發生原因是幾個錯綜複雜的寫法跟設定造成的,三言兩語難以解釋得清楚,簡單地說是網站本身就存在數個既有錯誤,最後又加上 customErrors 設定而造成一連串的 redirect 形成無限迴圈,customErrors 也就變成壓倒駱駝的最後一根稻草,成了替死鬼XD
過程中查了些資料也用 ASP.NET MVC 與 ASP.NET WEB API sample project 做了幾個實驗,順手紀錄一下,以供大家參考,如果是 webform 專案請參考 黑大的文章 customErrors與httpErrors
httpErrors
本機進行測試,記得把 errorMode 設定成 Custom
- 為網站或應用程式設定自定錯誤訊息
對應至 IIS - Error Pages 設定
httpErrors 的屬性(attribute)
attribute mandatory type default comment allowAbsolutePathsWhenDelegated optional boolean false -允許是否使用絕對路徑
-只能設定在 ApplicationHost.config 中,網站的 Web.config 不支援defaultPath optional string - - 指定自定錯誤頁面的預設路徑
- 路徑類型由 “defaultResponseMode” 指定:File
- 檔案路徑ExecuteURL
- 相對 URLRedirect
- 絕對 URLdefaultResponseMode optional enum 0(File) - 指定如何處理自訂錯誤
- File: 0, 指向靜態檔案
- ExecuteURL : 1, 指向動態內容,必須是 server 中的相對 URL
- Redirect : 2,redirect 其他網址,必須是絕對 URLdetailedMoreInformationLink optional string 官網 用來提供詳細錯誤資訊的網頁連結 errorMode optional enum 0(DetailedLocalOnly) - 是否啟用 HTTP error
- DetailedLocalOnly:0,如果是 local 就回應詳細錯誤訊息,否則就是自定錯誤
- Custom:1,永遠回傳自訂錯誤
- Detailed:2,永遠回傳詳細錯誤訊息existingResponse optional enum 0(Auto) 指定收到 http status code 代表錯誤時 (i.e. code>=400)該如何處理
- Auto:0,SetStatus 被設定時就不干涉依 response 處理,否則就依自訂錯誤處理
- Replace:1,一律依自訂錯誤處理
- PassThrough:2,一律依 response 處理- 關於 existingResponse
- 我自己做了幾個測試,結果如下
httpErrors 設定
```xml <httpErrors errorMode="Custom" existingResponse="PassThrough"> <remove statusCode="404" subStatusCode="-1" /> <error statusCode="404" path="/NotFound" responseMode="ExecuteURL"/> </httpErrors> ```
NotFoundController 的 Index action
```cs public ActionResult Index() { return Content("NotFound!!!!"); } ```
HomeController 的 Index action
```cs public ActionResult Index() { //Response.TrySkipIisCustomErrors = true;//用來指定 SetStatus flag return HttpNotFound(); } ```
測試結果截圖 1. 執行 NotFoundController 的 Index action
![2notfound](https://cloud.githubusercontent.com/assets/3851540/23617957/cbc200c6-02c9-11e7-83a0-44b4cf4614da.png) 2. 直接吐 404 ![3404](https://cloud.githubusercontent.com/assets/3851540/23617959/cbc80a48-02c9-11e7-9bdb-05e3d3020ea2.png)
測試結果整理
existingResponse設定\SetStatus|with SetStatus|without SetStatus :---|:---|:--- Auto|結果2|結果1 Replace|結果1|結果1 PassThrough|結果2|結果2
httpErrors 下的子項目
<error>
- 可以有多組
<error>
Attribute mandatory type Description path Required string - 指定自定錯誤頁面的預設路徑
- 路徑類型由responseMode
指定:File
- 檔案路徑ExecuteURL
- 相對 URLRedirect
- 絕對 URLprefixLanguageFilePath optional string 指定不包含語系的前綴路徑, c:\inetpub\custerr\en-us\404.htm, prefixLanguageFilePath=“c:\inetpub\custerr” responseMode optional enum 指定如何處理自訂錯誤
- File: 0, 指向靜態檔案
- ExecuteURL : 1, 指向動態內容,必須是 server 中的相對 URL
- Redirect : 2,redirect 其他網址,必須是絕對 URLstatusCode Required integer 指定處理的 http status code,接受 400 ~ 999 subStatusCode optional integer 指定處理的 http substatus code,接受 -1 ~ 999 - 可以有多組
<remove>
使用
<remove>
來移除繼承自上層 IIS 的特定 http error 設定e.g.
<remove statusCode="404" subStatusCode="-1" />
<clear>
則可以一次移除繼承自上層 IIS 的所有 http error 的設定
心得
- 主要用來處理靜態檔案
- 程式指定的回傳內容
- ASP.NET WEB API 程式面的錯誤
customErrors
本機進行測試,記得
- 把 mode 設定成
on
- 停用 ASP.NET MVC 預設的 ErrorHandler (filter.config)
- 把 mode 設定成
為 ASP.NET 應用程式提供自訂錯誤訊息
對應至 ASP.NET - .NET Error Pages 設定
customErrors 的屬性(attribute)
attribute mandatory comment defaultRedirect optional - 錯誤發生時 redirect 的 url,未指定會出現 runtime error
- url 可以是絕對及相對路徑mode required - 指定是否顯示自定錯誤
- On : 啟用自訂錯誤
- Off : 停用自訂錯誤,會顯示完整錯誤訊息
- RemoteOnly : 預設值,只在本機看得到詳細錯誤redirectMode optional - 指定如何處理原 request 的 url
- ResponseRedirect : URL 會不同
- ResponseRewrite : URL 不會改變,但在 MVC 中使用, path 必須使用實際存在的檔案,詳細原因請見 ASP.NET MVC 裡redirectMode=“ResponseRewrite” 時候無法使用 Controller 來設置特定的錯誤頁面customErrors 下的子項目
- error
- optional
- 可以有多組
<error>
- 指定特定 http status code 來自訂錯誤網頁
心得
- 用來處理 ASP.NET MVC 程式面的錯誤
兩者有重複地方 ?
兩個設定可以針對相同的 error code 做處理,那會由誰回應?
- 測試情境 1
- js call web api 回應 500 或是有 exception
- 由 httpErrors 處理
- 測試情境 2
- js call MVC controller action 回應 500 或是有 exception
- 由 customErros 處理
- 測試情境 3 (預設 - 使用內建 error handler)
- 直接 access MVC controller action 回應 500 或是有 exception
- 由 httpErrors 處理
- 測試情境 4 (關閉預設 error handler)
- 直接 access MVC controller action 回應 500 或是有 exception
- 由 customErros 處理
- 結論
- 靜態資源問題由 httpErrors 處理
- Web API 問題由 httpErrors 處理
- 預設情境下 MVC 問題由 httpErrors 處理
- 關閉 MVC 內建 error handler 後 MVC 問題由 customErros 處理
注意事項
- IIS 設定會寫入網站的 web.config,需留意部署會被覆蓋,建議直接加入專案的 web.config
- ASP.NET - .NET Error Pages 需安裝 IIS 的 ASP.NET module
- 本機測試時,需注意 error 是否正確
- MVC 專案有預設 error handler
參考資料
文章作者 Yowko Tsai
上次更新 2021-11-02
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。