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

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

正如我猜想它,由於ELMAH只記錄未處理的錯誤,[HandleError]屬性正在處理錯誤,所以無需記錄它。 mvc

我如何修改或如何修改屬性,以便ELMAH能夠知道有錯誤並記錄它.. app

編輯:讓我確保每一個人都理解,我知道我能夠修改那個不是我問的問題的屬性... ELMAH在使用handleerror屬性時會被繞過,這意味着它不會看到有錯誤由於它被處理了已經由屬性...我要問的是有一種方法讓ELMAH看到錯誤並記錄它即便屬性處理它...我搜索周圍,沒有看到任何方法調用強制它來記錄錯誤.... asp.net


#1樓

如今NuGet中有一個ELMAH.MVC包,其中包括Atif的改進解決方案以及處理MVC路由中的elmah接口的控制器(再也不須要使用該axd)
該解決方案(以及此處的全部解決方案)的問題在於,elmah錯誤處理程序其實是以某種方式處理錯誤,忽略了您可能想要設置爲customError標記或經過ErrorHandler或您本身的錯誤處理程序
最好的解決方案是IMHO建立一個過濾器,它將在全部其餘過濾器的末尾起做用,並記錄已經處理過的事件。 elmah模塊應該注意記錄應用程序未處理的其餘錯誤。 這還容許您使用運行情況監視器和可添加到asp.net的全部其餘模塊來查看錯誤事件 ide

我在elmah.mvc裏面的ErrorHandler中用反射器寫了這個 wordpress

public class ElmahMVCErrorFilter : IExceptionFilter
{
   private static ErrorFilterConfiguration _config;

   public void OnException(ExceptionContext context)
   {
       if (context.ExceptionHandled) //The unhandled ones will be picked by the elmah module
       {
           var e = context.Exception;
           var context2 = context.HttpContext.ApplicationInstance.Context;
           //TODO: Add additional variables to context.HttpContext.Request.ServerVariables for both handled and unhandled exceptions
           if ((context2 == null) || (!_RaiseErrorSignal(e, context2) && !_IsFiltered(e, context2)))
           {
            _LogException(e, context2);
           }
       }
   }

   private static bool _IsFiltered(System.Exception e, System.Web.HttpContext context)
   {
       if (_config == null)
       {
           _config = (context.GetSection("elmah/errorFilter") as ErrorFilterConfiguration) ?? new ErrorFilterConfiguration();
       }
       var context2 = new ErrorFilterModule.AssertionHelperContext((System.Exception)e, context);
       return _config.Assertion.Test(context2);
   }

   private static void _LogException(System.Exception e, System.Web.HttpContext context)
   {
       ErrorLog.GetDefault((System.Web.HttpContext)context).Log(new Elmah.Error((System.Exception)e, (System.Web.HttpContext)context));
   }


   private static bool _RaiseErrorSignal(System.Exception e, System.Web.HttpContext context)
   {
       var signal = ErrorSignal.FromContext((System.Web.HttpContext)context);
       if (signal == null)
       {
           return false;
       }
       signal.Raise((System.Exception)e, (System.Web.HttpContext)context);
       return true;
   }
}

如今,在您的過濾器配置中,您想要執行如下操做: ui

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //These filters should go at the end of the pipeline, add all error handlers before
        filters.Add(new ElmahMVCErrorFilter());
    }

請注意,我在那裏留下了一個註釋,提醒人們若是他們想要添加一個實際處理異常的全局過濾器,它應該在最後一個過濾器以前進行,不然你會遇到ElmahMVCErrorFilter忽略未處理異常的狀況,由於它沒有被處理,它應該由Elmah模塊提供,可是接下來的過濾器將異常標記爲已處理,模塊忽略它,致使異常從未使它成爲elmah。 spa

如今,確保webconfig中的elmah appsettings看起來像這樣: .net

<add key="elmah.mvc.disableHandler" value="false" /> <!-- This handles elmah controller pages, if disabled elmah pages will not work -->
<add key="elmah.mvc.disableHandleErrorFilter" value="true" /> <!-- This uses the default filter for elmah, set to disabled to use our own -->
<add key="elmah.mvc.requiresAuthentication" value="false" /> <!-- Manages authentication for elmah pages -->
<add key="elmah.mvc.allowedRoles" value="*" /> <!-- Manages authentication for elmah pages -->
<add key="elmah.mvc.route" value="errortracking" /> <!-- Base route for elmah pages -->

這裏重要的是「elmah.mvc.disableHandleErrorFilter」,若是這是假的,它將使用elmah.mvc中的處理程序,該處理程序將使用默認的HandleErrorHandler實際處理異常,該處理程序將忽略您的customError設置 日誌

此設置容許您在類和視圖中設置本身的ErrorHandler標記,同時仍經過ElmahMVCErrorFilter記錄這些錯誤,經過elmah模塊向web.config添加customError配置,甚至編寫本身的錯誤處理程序。 您惟一須要作的就是記住在咱們編寫的elmah過濾器以前不添加任何實際處理錯誤的過濾器。 我忘了提到:elmah沒有重複。


#2樓

一個徹底替代的解決方案是不使用MVC HandleErrorAttribute ,而是依賴於Elmah旨在使用的ASP.Net錯誤處理。

您須要從App_Start \\ FilterConfig(或Global.asax)中刪除默認的全局HandleErrorAttribute ,而後在Web.config中設置錯誤頁面:

<customErrors mode="RemoteOnly" defaultRedirect="~/error/" />

注意,這能夠是MVC路由URL,所以上面會在發生錯誤時重定向到ErrorController.Index操做。


#3樓

您能夠採用上面的代碼,並經過引入一個自定義控制器工廠更進一步,該工廠將HandleErrorWithElmah屬性注入每一個控制器。

有關更多信息,請查看我關於登陸MVC的博客系列。 第一篇文章介紹瞭如何讓Elmah爲MVC設置和運行。

本文末尾有一個可下載代碼的連接。 但願有所幫助。

http://dotnetdarren.wordpress.com/


#4樓

這正是個人MVC站點配置所須要的!

我添加了一些OnException方法的修改來處理多個HandleErrorAttribute實例,如Atif Aziz所建議的:

請記住,若是多個HandleErrorAttribute實例生效,您可能必須注意不會發生重複日誌記錄。

我只是在調用基類以前檢查context.ExceptionHandled ,只是爲了知道其餘人是否在當前處理程序以前處理了異常。
它適用於我,我發佈代碼,以防其餘人須要它,並詢問是否有人知道我是否忽略了任何東西。

但願它有用:

public override void OnException(ExceptionContext context)
{
    bool exceptionHandledByPreviousHandler = context.ExceptionHandled;

    base.OnException(context);

    Exception e = context.Exception;
    if (exceptionHandledByPreviousHandler
        || !context.ExceptionHandled  // if unhandled, will be logged anyhow
        || RaiseErrorSignal(e)        // prefer signaling, if possible
        || IsFiltered(context))       // filtered?
        return;

    LogException(e);
}

#5樓

對我來講,讓電子郵件日誌記錄工做很是重要。 通過一段時間後,我發如今Atif示例中只須要2行代碼。

public class HandleErrorWithElmahAttribute : HandleErrorAttribute
{
    static ElmahMVCMailModule error_mail_log = new ElmahMVCMailModule();

    public override void OnException(ExceptionContext context)
    {
        error_mail_log.Init(HttpContext.Current.ApplicationInstance);
        [...]
    }
    [...]
}

我但願這會幫助別人:)

相關文章
相關標籤/搜索