首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET Global.asax 攔截 404 錯誤並導向自訂頁面的實作

     編輯:ASP.NET 基礎

實作目標

在 Global.asax 的 Application_Error 事件中攔截未處理的例外,針對 HTTP 404 (找不到頁面) 導向友善的自訂錯誤頁面,其他錯誤導向通用錯誤頁或記錄日誌。

完整程式碼

void Application_Error(object sender, EventArgs e)
{
    // 1. 取得目前 HttpContext 與最後發生的例外
    HttpContext ctx = HttpContext.Current;
    Exception ex = ctx.Server.GetLastError();

    // 2. 嘗試轉型為 HttpException (含 HTTP 狀態碼)
    HttpException httpEx = ex as HttpException;

    if (httpEx != null)
    {
        int httpCode = httpEx.GetHttpCode();

        // 3. 專門處理 404
        if (httpCode == 404)
        {
            // 清除錯誤狀態,避免觸發 customErrors 再次導向
            ctx.ClearError();
            
            // 導向自訂 404 頁面 (false = 不終止執行緒,讓 Response 完成)
            ctx.Response.Redirect("~/NotFound.aspx", false);
            
            // 確保後續程式碼不執行
            ctx.Response.End();
            return;
        }
    }

    // 4. 非 404 錯誤:導向通用錯誤頁或記錄日誌
    // 這裡使用 Server.Transfer 保持原始 URL (方便記錄/除錯)
    ctx.Server.Transfer("~/Error.aspx", false);
}

關鍵技術點解析

方法/屬性用途
ctx.Server.GetLastError()取得導致錯誤的原始例外物件
HttpException.GetHttpCode()取得 HTTP 狀態碼 (404, 500, 403...)
ctx.ClearError()清除錯誤狀態,防止 ASP.NET 預設錯誤處理流程介入
Response.Redirect(url, false)導向新頁面,false 表示不呼叫 Response.End() (避免 ThreadAbortException)
Response.End()立即結束回應,確保不再執行後續程式碼
Server.Transfer(url, false)伺服器端轉交,URL 不變,保持原始請求資訊

搭配 web.config customErrors 區段

雖然 Application_Error 可完全掌控,但建議保留 customErrors 作為第二層防線:

<system.web>
    <customErrors mode="RemoteOnly" defaultRedirect="~/Error.aspx">
        <error statusCode="404" redirect="~/NotFound.aspx" />
        <error statusCode="500" redirect="~/ServerError.aspx" />
    </customErrors>
</system.web>
  • mode="RemoteOnly":本機開發顯示詳細錯誤 (黃色死機畫面),遠端使用者看自訂頁面。
  • Application_Error 優先順序高於 customErrors,故需呼叫 ClearError() 避免衝突。

自訂 404 頁面 NotFound.aspx 範例

<%@ Page Language="C#" %>
<html><head><title>頁面不存在</title></head><body>
<div style="text-align:center; padding:50px;">
    <h1>404 - 找不到頁面</h1>
    <p>您請求的頁面可能已移除、更名或暫時無法使用。</p>
    <p>
        <a href="/">返回首頁</a> | 
        <a href="javascript:history.back()">上一頁</a> | 
        <a href="/SiteMap.aspx">網站地圖</a>
    </p>
</div>
</body></html>

進階:記錄 404 詳細資訊供 SEO 分析

if (httpCode == 404)
{
    // 記錄至資料庫/日誌
    string requestedUrl = ctx.Request.Url.ToString();
    string referrer = ctx.Request.UrlReferrer?.ToString() ?? "無";
    string userAgent = ctx.Request.UserAgent;
    string userIp = ctx.Request.UserHostAddress;
    
    Log404(requestedUrl, referrer, userAgent, userIp); // 自訂記錄方法
    
    ctx.ClearError();
    ctx.Response.Redirect("~/NotFound.aspx", false);
    ctx.Response.End();
}

注意事項

  • 靜態檔案 404 不會觸發:.jpg、.css、.js 等靜態資源由 IIS 直接處理,不經 ASP.NET 管線。需在 IIS 設定自訂錯誤頁面或對應 managedHandler。
  • 避免在 Application_Error 中拋出新例外:會導致無限迴圈或遮蔽原始錯誤。
  • ELMAH / Serilog 等日誌框架:生產環境建議整合專業日誌庫,自動記錄堆疊追蹤、請求內容。
  • ASP.NET Core:使用 app.UseStatusCodePagesWithReExecute("/Error/{0}") 中介軟體取代 Global.asax。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved