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

ASP.NET MVC 異常處理三種方案:全域、控制器、過濾器

     編輯:ASP.NET 基礎

方案一:全域 Application_Error(Global.asax)

protected void Application_Error(object sender, EventArgs e)
{
    var ex = Server.GetLastError().GetBaseException();
    var msg = $"{DateTime.Now}: {Request.Url}\n{ex.Message}\n{ex.StackTrace}";
    LogToFile(msg); // 自訂寫入檔案/資料庫/ELMAH/Serilog
    Server.ClearError();
    Response.Redirect("/Error/Index"); // 導向友善錯誤頁
}

優點:攔截所有未處理異常;缺點:難以依異常類型差異化處理、不支援 AJAX 請求回傳 JSON。

方案二:控制器重寫 OnException

public class BaseController : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.ExceptionHandled) return;

        LogException(filterContext.Exception);
        filterContext.ExceptionHandled = true;

        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.Result = Json(new { success = false, message = "伺服器錯誤" });
        }
        else
        {
            filterContext.Result = View("Error");
        }
    }
}

優點:可在基類統一處理、支援 AJAX/一般請求區分;缺點:需所有控制器繼承基類。

方案三:自訂 HandleErrorAttribute 過濾器(推薦)

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class CustomHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
            return;

        var ex = filterContext.Exception;
        LogException(ex); // 整合 Serilog/NLog/ELMAH

        if (new HttpRequestWrapper(filterContext.HttpContext.Request).IsAjaxRequest())
        {
            filterContext.Result = new JsonResult
            {
                Data = new { error = ex.Message },
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }
        else
        {
            var viewName = View ?? "Error";
            filterContext.Result = new ViewResult
            {
                ViewName = viewName,
                ViewData = new ViewDataDictionary<HandleErrorInfo>(new HandleErrorInfo(ex, ControllerName, ActionName))
            };
        }
        filterContext.ExceptionHandled = true;
    }
}

註冊為全域過濾器

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new CustomHandleErrorAttribute());
        // filters.Add(new HandleErrorAttribute()); // 內建簡易版
    }
}

現代化建議:整合結構化日誌框架

  • Serilog + Seq/Elasticsearch:結構化日誌、豐富查詢、告警。
  • NLog:高效能、多目標支援。
  • ELMAH:專為 ASP.NET 設計,自動記錄黃屏、支援資料庫/郵件/記憶體存儲。

錯誤頁面最佳實踐

  • web.config 設定 <customErrors mode="On" defaultRedirect="/Error">。
  • 區分 404、500 等狀態碼顯示專屬視圖。
  • 生產環境關閉詳細錯誤資訊,避免洩露堆疊追蹤。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved