В NuGet теперь есть пакет ELMAH.MVC, который включает в себя улучшенное решение Atif, а также контроллер, который обрабатывает интерфейс elmah в маршрутизации MVC (больше не нужно использовать этот axd)
Проблема с этим решением (и со всеми здесь) заключается в том, что так или иначе обработчик ошибок elmah фактически обрабатывает ошибку, игнорируя то, что вы можете захотеть установить как тег customError или через ErrorHandler или ваш собственный обработчик ошибок
Лучшее решение IMHO - создать фильтр, который будет действовать в конце всех других фильтров и регистрировать события, которые уже были обработаны. Модуль elmah должен позаботиться о регистрации других ошибок, которые не обрабатываются приложением. Это также позволит вам использовать монитор работоспособности и все другие модули, которые можно добавить на asp.net, для просмотра событий ошибок
Я написал это, глядя отражателем на ErrorHandler внутри elmah.mvc
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.
Теперь убедитесь, что настройки app для elmah в вашем webconfig выглядят примерно так:
<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, добавляя конфигурацию customError в ваш web.config через модуль elmah, даже записывая свои собственные обработчики ошибок. Единственное, что вам нужно сделать, - это не добавлять фильтры, которые будут обрабатывать ошибку, до того, как мы написали фильтр elmah. И я забыл упомянуть: в Эльме нет дубликатов.