我正在嘗試使用ELMAH來記錄個人ASP.NET MVC應用程序中的錯誤,可是當我在控制器上使用[HandleError]屬性時,ELMAH在發生錯誤時不會記錄任何錯誤。 web
正如我猜想它,由於ELMAH只記錄未處理的錯誤,[HandleError]屬性正在處理錯誤,所以無需記錄它。 mvc
我如何修改或如何修改屬性,以便ELMAH能夠知道有錯誤並記錄它.. app
編輯:讓我確保每一個人都理解,我知道我能夠修改那個不是我問的問題的屬性... ELMAH在使用handleerror屬性時會被繞過,這意味着它不會看到有錯誤由於它被處理了已經由屬性...我要問的是有一種方法讓ELMAH看到錯誤並記錄它即便屬性處理它...我搜索周圍,沒有看到任何方法調用強制它來記錄錯誤.... asp.net
如今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沒有重複。
一個徹底替代的解決方案是不使用MVC HandleErrorAttribute
,而是依賴於Elmah旨在使用的ASP.Net錯誤處理。
您須要從App_Start \\ FilterConfig(或Global.asax)中刪除默認的全局HandleErrorAttribute
,而後在Web.config中設置錯誤頁面:
<customErrors mode="RemoteOnly" defaultRedirect="~/error/" />
注意,這能夠是MVC路由URL,所以上面會在發生錯誤時重定向到ErrorController.Index
操做。
您能夠採用上面的代碼,並經過引入一個自定義控制器工廠更進一步,該工廠將HandleErrorWithElmah屬性注入每一個控制器。
有關更多信息,請查看我關於登陸MVC的博客系列。 第一篇文章介紹瞭如何讓Elmah爲MVC設置和運行。
本文末尾有一個可下載代碼的連接。 但願有所幫助。
http://dotnetdarren.wordpress.com/
這正是個人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); }
對我來講,讓電子郵件日誌記錄工做很是重要。 通過一段時間後,我發如今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); [...] } [...] }
我但願這會幫助別人:)