Il y a maintenant un package ELMAH.MVC dans NuGet qui inclut une solution améliorée par Atif et également un contrôleur qui gère l'interface elmah dans le routage MVC (plus besoin d'utiliser cet axd)
Le problème avec cette solution (et avec toutes celles ici) ) est que d'une manière ou d'une autre, le gestionnaire d'erreurs elmah gère réellement l'erreur, ignorant ce que vous pouvez configurer en tant que balise customError ou via ErrorHandler ou votre propre gestionnaire d'erreurs
La meilleure solution à mon humble avis est de créer un filtre qui agira à la fin de tous les autres filtres et enregistrera les événements qui ont déjà été traités. Le module elmah doit prendre en charge la journalisation des autres erreurs non gérées par l'application. Cela vous permettra également d'utiliser le moniteur de santé et tous les autres modules qui peuvent être ajoutés à asp.net pour consulter les événements d'erreur
J'ai écrit ceci en regardant avec un réflecteur au ErrorHandler à l'intérieur d'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;
}
}
Maintenant, dans votre configuration de filtre, vous voulez faire quelque chose comme ceci:
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());
}
Notez que j'ai laissé un commentaire là pour rappeler aux gens que s'ils veulent ajouter un filtre global qui gérera réellement l'exception, il devrait aller AVANT ce dernier filtre, sinon vous rencontrez le cas où l'exception non gérée sera ignorée par ElmahMVCErrorFilter car il n'a pas été géré et il devrait être journalisé par le module Elmah mais le filtre suivant marque l'exception comme gérée et le module l'ignore, ce qui fait que l'exception ne se transforme jamais en elmah.
Maintenant, assurez-vous que les paramètres d'application pour Elmah dans votre configuration Web ressemblent à ceci:
<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 -->
L'important ici est "elmah.mvc.disableHandleErrorFilter", si c'est faux, il utilisera le gestionnaire à l'intérieur d'elmah.mvc qui gérera réellement l'exception en utilisant le HandleErrorHandler par défaut qui ignorera vos paramètres d'erreur personnalisés
Cette configuration vous permet de définir vos propres balises ErrorHandler dans les classes et les vues, tout en enregistrant ces erreurs via ElmahMVCErrorFilter, en ajoutant une configuration customError à votre web.config via le module elmah, et même en écrivant vos propres gestionnaires d'erreur. La seule chose que vous devez faire est de ne pas ajouter de filtres qui gèreront réellement l'erreur avant le filtre elmah que nous avons écrit. Et j'ai oublié de mentionner: pas de doublons dans Elmah.