W NuGet jest teraz pakiet ELMAH.MVC, który zawiera ulepszone rozwiązanie firmy Atif, a także kontroler, który obsługuje interfejs elmah w ramach routingu MVC (nie trzeba już używać tego axd)
. Problem z tym rozwiązaniem (i wszystkimi tymi tutaj ) jest to, że w ten czy inny sposób moduł obsługi błędów Elmah faktycznie obsługuje błąd, ignorując to, co możesz ustawić jako niestandardowy tagError lub za pośrednictwem narzędzia ErrorHandler lub własnego programu obsługi błędów
Najlepszym rozwiązaniem IMHO jest utworzenie filtra, który będzie działał na końcu wszystkich innych filtrów i rejestrował zdarzenia, które zostały już obsłużone. Moduł elmah powinien zająć się rejestrowaniem innych błędów, które nie są obsługiwane przez aplikację. Umożliwi to również użycie monitora kondycji i wszystkich innych modułów, które można dodać do asp.net w celu sprawdzenia zdarzeń błędów
Napisałem to patrząc z odbłyśnikiem na ErrorHandler wewnątrz 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;
}
}
Teraz w konfiguracji filtra chcesz zrobić coś takiego:
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());
}
Zauważ, że zostawiłem tam komentarz, aby przypomnieć ludziom, że jeśli chcą dodać filtr globalny, który faktycznie obsłuży wyjątek, powinien przejść PRZED tym ostatnim filtrem, w przeciwnym razie natrafisz na przypadek, w którym nieobsługiwany wyjątek zostanie zignorowany przez filtr ElmahMVCError, ponieważ nie został obsłużony i powinien zostać zarejestrowany przez moduł Elmah, ale następnie następny filtr oznacza wyjątek jako obsłużony, a moduł go ignoruje, co powoduje, że wyjątek nigdy nie przekształca się w elmah.
Teraz upewnij się, że ustawienia elmah w konfiguracji sieciowej wyglądają mniej więcej tak:
<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 -->
Ważnym tutaj jest „elmah.mvc.disableHandleErrorFilter”, jeśli jest to fałsz, użyje on modułu obsługi w elmah.mvc, który faktycznie obsłuży wyjątek, używając domyślnego HandleErrorHandler, który zignoruje twoje ustawienia customError
Ta konfiguracja pozwala ustawić własne tagi ErrorHandler w klasach i widokach, jednocześnie rejestrując te błędy za pomocą ElmahMVCErrorFilter, dodając konfigurację customError do pliku web.config za pośrednictwem modułu elmah, a nawet pisząc własne programy obsługi błędów. Jedyne, co musisz zrobić, to pamiętać, aby nie dodawać żadnych filtrów, które faktycznie obsługiwałyby błąd przed napisanym przez nas filtrem elmah. I zapomniałem wspomnieć: nie ma duplikatów w elmie.