ASP.NET 提供三層錯誤處理機制:頁面層級(Page_Error)、應用程式層級(Application_Error)與組態層級(Web.config <customErrors>)。善用這三層可建立健全的錯誤記錄、使用者友善提示與安全性防護。
適用於單一頁面的例外處理,可記錄詳細錯誤或導向友善頁面。
// PageEvent.aspx.cs
void Page_Load(object sender, EventArgs e)
{
throw new ArgumentNullException(); // 測試用強制拋出例外
}
public void Page_Error(object sender, EventArgs e)
{
Exception objErr = Server.GetLastError().GetBaseException();
string err = "<b>Error Caught in Page_Error</b><hr/>" +
"<br/><b>Error in:</b> " + Request.Url +
"<br/><b>Message:</b> " + objErr.Message +
"<br/><b>Stack Trace:</b><br/> " + objErr.StackTrace;
Response.Write(err);
Server.ClearError(); // 阻止錯誤繼續傳播至 Application_Error
}
注意:生產環境切勿直接輸出堆疊追蹤給使用者,應改為寫入日誌並顯示通用錯誤訊息。
在 Global.asax 中實作,適合集中記錄所有未處理例外至事件日誌或資料庫。
// Global.asax
using System.Diagnostics;
protected void Application_Error(object sender, EventArgs e)
{
Exception objErr = Server.GetLastError().GetBaseException();
string err = "Error Caught in Application_Error\n" +
"Error in: " + Request.Url + "\n" +
"Message: " + objErr.Message + "\n" +
"Stack Trace: " + objErr.StackTrace;
EventLog.WriteEntry("MyWebApp", err, EventLogEntryType.Error);
// Server.ClearError(); // 若註解掉,錯誤會繼續傳遞給 customErrors
}
當上兩層未呼叫 Server.ClearError() 或未捕捉錯誤時,ASP.NET 依此設定導向自訂錯誤頁面。
<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPages/GeneralError.htm">
<error statusCode="404" redirect="~/ErrorPages/NotFound.htm" />
<error statusCode="500" redirect="~/ErrorPages/ServerError.htm" />
</customErrors>
mode="On":所有使用者導向錯誤頁(生產環境)。mode="Off":顯示詳細 ASP.NET 錯誤頁(開發環境)。mode="RemoteOnly":本機顯示詳細錯誤,遠端導向錯誤頁(推薦預設)。若錯誤頁為 .aspx 需使用 Server.GetLastError(),需在 Application_Error 中將例外存入 Session 或 HttpContext.Items,因導向會重置 Server.GetLastError()。
// Global.asax
protected void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
Session["LastError"] = ex; // 或 Context.Items["LastError"] = ex;
// 不呼叫 Server.ClearError(),讓 customErrors 處理導向
}
// ErrorPage.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
Exception ex = Session["LastError"] as Exception;
if (ex != null) { /* 記錄或顯示 */ Session.Remove("LastError"); }
}
| 層級 | 適用場景 | 關鍵點 |
|---|---|---|
| Page_Error | 特定頁面商業邏輯例外、局部降級處理 | 務必呼叫 Server.ClearError() 防止重複處理 |
| Application_Error | 全域例外日誌記錄、統一錯誤通知 | 避免吞沒例外,至少記錄完整堆疊 |
| customErrors | 使用者友善錯誤頁面、HTTP 狀態碼對應 | 搭配 mode="RemoteOnly" 平衡開發與安全 |
三層機制互補,建立「記錄完整、使用者友善、資訊不洩漏」的錯誤處理體系。