Теперь в 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. И я забыл упомянуть: в Эльме нет дубликатов.