Asp.net-Mvc

如何讓 ELMAH 與 ASP.NET MVC [HandleError] 屬性一起使用?

  • April 20, 2009

我正在嘗試使用 ELMAH 在我的 ASP.NET MVC 應用程序中記錄錯誤,但是當我在控制器上使用 [HandleError] 屬性時,ELMAH 在發生錯誤時不會記錄任何錯誤。

正如我猜測的那樣,因為 ELMAH 只記錄未處理的錯誤,而 [HandleError] 屬性正在處理錯誤,因此無需記錄它。

我如何修改或如何修改屬性,以便 ELMAH 可以知道存在錯誤並記錄它..

**編輯:**讓我確保每個人都理解,我知道我可以修改屬性,這不是我要問的問題…使用 handleerror 屬性時,ELMAH 被繞過,這意味著它不會看到有錯誤,因為它已被處理已經由屬性…我要問的是有沒有辦法讓 ELMAH 看到錯誤並記錄它,即使屬性處理了它…我四處搜尋,沒有看到任何方法可以呼叫來強制它記錄錯誤….

您可以子類化HandleErrorAttribute並覆蓋其OnException成員(無需複制),以便它使用 ELMAH 記錄異常,並且僅當基本實現處理它時。您需要的最少程式碼如下:

using System.Web.Mvc;
using Elmah;

public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
   public override void OnException(ExceptionContext context)
   {
       base.OnException(context);
       if (!context.ExceptionHandled) 
           return;
       var httpContext = context.HttpContext.ApplicationInstance.Context;
       var signal = ErrorSignal.FromContext(httpContext);
       signal.Raise(context.Exception, httpContext);
   }
}

首先呼叫基本實現,使其有機會將異常標記為正在處理。只有這樣才會發出異常信號。HttpContext上面的程式碼很簡單,如果在測試等可能不可用的環境中使用,可能會導致問題。因此,您將需要更具防禦性的程式碼(以稍長一些為代價):

using System.Web;
using System.Web.Mvc;
using Elmah;

public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
   public override void OnException(ExceptionContext context)
   {
       base.OnException(context);
       if (!context.ExceptionHandled       // if unhandled, will be logged anyhow
           || TryRaiseErrorSignal(context) // prefer signaling, if possible
           || IsFiltered(context))         // filtered?
           return;

       LogException(context);
   }

   private static bool TryRaiseErrorSignal(ExceptionContext context)
   {
       var httpContext = GetHttpContextImpl(context.HttpContext);
       if (httpContext == null)
           return false;
       var signal = ErrorSignal.FromContext(httpContext);
       if (signal == null)
           return false;
       signal.Raise(context.Exception, httpContext);
       return true;
   }

   private static bool IsFiltered(ExceptionContext context)
   {
       var config = context.HttpContext.GetSection("elmah/errorFilter")
                       as ErrorFilterConfiguration;

       if (config == null)
           return false;

       var testContext = new ErrorFilterModule.AssertionHelperContext(
                             context.Exception, 
                             GetHttpContextImpl(context.HttpContext));
       return config.Assertion.Test(testContext);
   }

   private static void LogException(ExceptionContext context)
   {
       var httpContext = GetHttpContextImpl(context.HttpContext);
       var error = new Error(context.Exception, httpContext);
       ErrorLog.GetDefault(httpContext).Log(error);
   }

   private static HttpContext GetHttpContextImpl(HttpContextBase context)
   {
       return context.ApplicationInstance.Context;
   }
}

第二個版本將首先嘗試使用來自 ELMAH 的錯誤信號,這涉及到完全配置的管道,如日誌記錄、郵件、過濾和你有什麼。如果做不到這一點,它會嘗試查看是否應該過濾錯誤。如果不是,則簡單地記錄錯誤。此實現不處理郵件通知。如果可以發出異常信號,則如果配置為發送郵件,則會發送郵件。

您可能還必須注意,如果多個HandleErrorAttribute實例生效,則不會發生重複日誌記錄,但上述兩個範例應該可以幫助您入門。

引用自:https://stackoverflow.com/questions/766610