NuGet 中现在有一个 ELMAH.MVC 包,其中包括 Atif 改进的解决方案以及处理 MVC 路由中的 elmah 接口的控制器(不再需要使用该 axd)
该解决方案的问题(以及此处的所有问题) ) 是 elmah 错误处理程序实际处理错误的一种或另一种方式,而忽略了您可能希望设置为 customError 标记或通过 ErrorHandler 或您自己的错误处理程序设置的内容
恕我直言,最好的解决方案是创建一个过滤器,它将在所有其他过滤器的末尾起作用并记录已经处理的事件。elmah 模块应该负责记录应用程序未处理的其他错误。这也将允许您使用运行状况监视器和可以添加到 asp.net 的所有其他模块来查看错误事件
我用反射器在 elmah.mvc 中的 ErrorHandler 上写了这个
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 标签,同时仍通过 ElmahMVCErrorFilter 记录这些错误,通过 elmah 模块将 customError 配置添加到 web.config,甚至编写自己的错误处理程序。您唯一需要做的就是记住不要在我们编写的 elmah 过滤器之前添加任何实际处理错误的过滤器。我忘了提:elmah 中没有重复项。