There is now an ELMAH.MVC package in NuGet that includes an improved solution by Atif and also a controller that handles the elmah interface within MVC routing (no need to use that axd anymore)
The problem with that solution (and with all the ones here) is that one way or another the elmah error handler is actually handling the error, ignoring what you might want to set up as a customError tag or through ErrorHandler or your own error handler
The best solution IMHO is to create a filter that will act at the end of all the other filters and log the events that have been handled already. The elmah module should take care of loging the other errors that are unhandled by the application. This will also allow you to use the health monitor and all the other modules that can be added to asp.net to look at error events
我在elmah.mvc中的ErrorHandler中使用reflector写了这个
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;
}
}
现在,在你的过滤器配置中,你想做这样的事情:
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产生的异常。
现在,确保在你的webconfig中elmah的appsettings看起来像这样:
<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”,如果为false,它将使用elmah内部的处理程序。mvc,它会使用默认的HandleErrorHandler来处理异常,它会忽略你的customError设置
此设置允许您在类和视图中设置自己的ErrorHandler标记,同时仍然通过elmahvcerrorfilter记录这些错误,并将customError配置添加到您的web。通过elmah模块配置,甚至编写自己的错误处理程序。你需要做的唯一一件事就是记住不要在我们编写的elmah过滤器之前添加任何实际处理错误的过滤器。我忘了说,埃尔玛体内没有复制体。