ASP.NET 三層錯誤處理機制
| 層級 | 事件/設定 | 適用範圍 |
| 頁面 | Page_Error | 單一 .aspx 頁面 |
| 應用程式 | Application_Error (Global.asax) | 全站所有未捕獲例外 |
| 設定檔 | <customErrors> / <httpErrors> | 靜態錯誤頁面導向 |
Page_Error 實作範例
<script language="C#" runat="server">
void Page_Load(object sender, EventArgs e)
{
// 故意拋出例外供測試
throw new ArgumentNullException("測試 Page_Error 捕獲");
}
protected void Page_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError().GetBaseException(); // 取得最內層例外
string errorMsg = "1. 發生頁面: " + Request.Url + "<br/>" +
"2. 錯誤訊息: " + ex.Message + "<br/>" +
"3. 堆疊追蹤: " + ex.StackTrace.Replace("\n", "<br/>");
Response.Write(errorMsg); // 開發階段顯示詳細資訊
// 生產環境建議:
// Response.Redirect("~/ErrorPage.aspx"); // 導向友善錯誤頁
// LogHelper.Error(ex); // 記錄至 Log/資料庫/事件檢視器
Server.ClearError(); // 必須清除,否則會繼續冒泡至 Application_Error
}
</script>
關鍵方法說明
Server.GetLastError():取得當前未處理的例外(最外層)。
.GetBaseException():遞迴取得最內層真正原因(略過包裝例外)。
Server.ClearError():標記例外已處理,阻止向上傳播至 Application_Error 或顯示黃色死機畫面 (YSOD)。
生產環境最佳實務
- 勿直接向使用者顯示堆疊追蹤(資安風險),應導向友善錯誤頁(
customErrors mode="RemoteOnly")。
- 集中記錄:使用 NLog、Serilog、log4net 或內建
System.Diagnostics.EventLog 寫入 Windows 事件檢視器。
Page_Error 優先級高於 Application_Error,若頁面已處理並 ClearError(),全域事件將不會觸發。
- 針對 AJAX/AsyncPostBack 錯誤,需在
ScriptManager.AsyncPostBackError 處理並回傳 JSON 錯誤資訊。
Web.config 友善錯誤頁設定
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="~/Error.aspx">
<error statusCode="404" redirect="~/404.aspx" />
<error statusCode="500" redirect="~/500.aspx" />
</customErrors>
</system.web>
<!-- IIS 7+ 整合管線 -->
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" /><error statusCode="404" path="/404.aspx" responseMode="ExecuteURL" />
<remove statusCode="500" /><error statusCode="500" path="/500.aspx" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>