我正在尝试使用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); [...] } [...] }
我但愿这会帮助别人:)