558 votos

Cómo obtener ELMAH para trabajar con ASP.NET MVC [HandleError] atributo?

Estoy tratando de usar ELMAH a errores de registro en mi ASP.NET aplicación MVC, sin embargo cuando uso el [HandleError] atributo en mi controladores de ELMAH no registro de los errores cuando se producen.

Como supongo que es porque ELMAH sólo los registros de errores no controlados y la [HandleError] atributo es el manejo del error, por lo que por lo tanto no hay necesidad de registro.

¿Cómo puedo modificar o cómo voy a ir yo acerca de cómo modificar el atributo de modo de ELMAH puede saber que hay un error y de registro..

Edit: me Deja asegúrese de que todo el mundo entiende, yo sé que puedo modificar el atributo eso no es la pregunta que estoy haciendo... ELMAH obtiene omite cuando se utiliza el atributo handleerror lo que significa que no vea que hay un error porque era manejado ya por el atributo... Lo que yo estoy pidiendo es que hay una manera de hacer ELMAH ver el error y de registro a pesar de que el atributo maneja...busqué alrededor y no ve nada métodos para llamar a la fuerza para registrar el error....

497voto

Atif Aziz Puntos 16967

Puede subclase HandleErrorAttribute y anular su OnException miembro (no es necesario para copiar) para que registra la excepción con ELMAH y sólo si la base de aplicación lo maneja. La mínima cantidad de código necesario es el siguiente:

using System.Web.Mvc;
using Elmah;

public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        base.OnException(context);
        if (!context.ExceptionHandled) 
            return;
        var httpContext = context.HttpContext.ApplicationInstance.Context;
        var signal = ErrorSignal.FromContext(httpContext);
        signal.Raise(context.Exception, httpContext);
    }
}

La base de la aplicación se invoca en primer lugar, darle una oportunidad para marcar la excepción, ya que se manipula. Sólo entonces es la excepción, ha señalado. El código anterior es simple y puede provocar problemas si se usa en un entorno donde la HttpContext pueden no estar disponibles, tales como pruebas. Como resultado, usted querrá código que es el que está más a la defensiva (en el costo de ser un poco más):

using System.Web;
using System.Web.Mvc;
using Elmah;

public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        base.OnException(context);
        if (!context.ExceptionHandled       // if unhandled, will be logged anyhow
            || TryRaiseErrorSignal(context) // prefer signaling, if possible
            || IsFiltered(context))         // filtered?
            return;

        LogException(context);
    }

    private static bool TryRaiseErrorSignal(ExceptionContext context)
    {
        var httpContext = GetHttpContextImpl(context.HttpContext);
        if (httpContext == null)
            return false;
        var signal = ErrorSignal.FromContext(httpContext);
        if (signal == null)
            return false;
        signal.Raise(context.Exception, httpContext);
        return true;
    }

    private static bool IsFiltered(ExceptionContext context)
    {
        var config = context.HttpContext.GetSection("elmah/errorFilter")
                        as ErrorFilterConfiguration;

        if (config == null)
            return false;

        var testContext = new ErrorFilterModule.AssertionHelperContext(
                              context.Exception, 
                              GetHttpContextImpl(context.HttpContext));
        return config.Assertion.Test(testContext);
    }

    private static void LogException(ExceptionContext context)
    {
        var httpContext = GetHttpContextImpl(context.HttpContext);
        var error = new Error(context.Exception, httpContext);
        ErrorLog.GetDefault(httpContext).Log(error);
    }

    private static HttpContext GetHttpContextImpl(HttpContextBase context)
    {
        return context.ApplicationInstance.Context;
    }
}

Esta segunda versión se intenta utilizar el error de señalización de ELMAH primera, que implica totalmente configurado canalización como la tala, de correo, filtrado y lo que tiene. En su defecto, intenta a ver si el error se debe ser filtrada. Si no, el error es simplemente registrarse. Esta aplicación no se ocupa de las notificaciones de correo. Si la excepción se puede señalar, a continuación, se envía un mail si está configurado para hacerlo.

Usted puede también tener cuidado de que si varios HandleErrorAttribute casos son, en efecto, a continuación, duplicar el registro no se produce, pero los dos ejemplos anteriores debe obtener su comenzado.

297voto

Ivan Zlatev Puntos 4844

Lo siento, pero creo que el aceptado respuesta es una exageración. Todo lo que necesitas hacer es esto:

public class ElmahHandledErrorLoggerFilter : IExceptionFilter
{
    public void OnException (ExceptionContext context)
    {
        // Log only handled exceptions, because all other will be caught by ELMAH anyway.
        if (context.ExceptionHandled)
            ErrorSignal.FromCurrentContext().Raise(context.Exception);
    }
}

y, a continuación, registrar (el orden es importante) en Global.asax.cs:

public static void RegisterGlobalFilters (GlobalFilterCollection filters)
{
    filters.Add(new ElmahHandledErrorLoggerFilter());
    filters.Add(new HandleErrorAttribute());
}

14voto

Raul Vejar Puntos 514

Ahora hay una ELMAH.MVC paquete de NuGet que incluye una solución mejorada por Atif y también un controlador que controla el elmah interfaz dentro de MVC de enrutamiento (no es necesario el uso que axd más)
El problema con esta solución (y con todas las de aquí) es que de una manera u otra la elmah error de controlador en realidad es la manipulación de el error, ignorando lo que usted puede ser que desee configurar como un customError etiqueta o a través de ErrorHandler o su propio manejador de errores
La mejor solución en mi humilde opinión, es crear un filtro que va a actuar al final de todos los otros filtros y el registro de los eventos que se han manejado ya. El elmah módulo debe tener cuidado de claves de acceso de los demás errores no controlada en la aplicación. Esto también le permitirá utilizar el monitor de salud y todos los otros módulos que se pueden añadir a asp.net mirar a los eventos de error

Escribí esta mirando con reflector en la ErrorHandler dentro de 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;
   }
}

Ahora, en su filtro de configuración que desea hacer algo como esto:

    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());
    }

Aviso que he dejado un comentario allí para recordarle a la gente que si quieren agregar un filtro global que va a manejar la excepción de que se debe ir ANTES de que este último filtro, de lo contrario corre en el caso de que la excepción no será ignorado por el ElmahMVCErrorFilter porque no ha sido manipulado y que debe ser decidiria por el Elmah módulo, pero luego el siguiente filtro marca la excepción, ya que se manejan y el módulo ignora, lo que resulta en la excepción nunca lo que es en elmah.

Ahora, asegúrese de que el appsettings para elmah en su webconfig ser algo como esto:

<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 -->

El importante aquí es "elmah.mvc.disableHandleErrorFilter", si este es falso que se utilice el controlador dentro de elmah.mvc que realmente manejan la excepción utilizando el valor predeterminado HandleErrorHandler que se omita su customError configuración

Esta configuración le permite establecer su propio ErrorHandler etiquetas en las clases y puntos de vista, mientras todavía claves de acceso a los errores a través de la ElmahMVCErrorFilter, la adición de un customError configuración web.config a través de la elmah módulo, e incluso escribir tus propios Controladores de Error. La única cosa que usted necesita recordar es no agregar alguno de los filtros que realmente manejan el error antes de que el elmah filtro que he escrito. Y me olvidé de mencionar: no duplicados en elmah.

7voto

Darren Puntos 194

Usted puede tomar el código de arriba e ir un paso más allá mediante la introducción de un controlador personalizado de la fábrica que inyecta el HandleErrorWithElmah atributo en cada controlador.

Para más información, echa un vistazo a mi blog de la serie en el registro en MVC. El primer artículo trata de llegar Elmah configurado y funcionando para MVC.

Hay un enlace con código de descarga al final del artículo. Espero que ayude.

http://dotnetdarren.wordpress.com/

6voto

user716264 Puntos 87

Soy nuevo en ASP.NET MVC. Yo se enfrentó al mismo problema, el siguiente es mi viable en mi Erorr.vbhtml (trabajo si usted sólo necesita ingresar el error en la utilización de Elmah registro)

@ModelType System.Web.Mvc.HandleErrorInfo

    @Code
        ViewData("Title") = "Error"
        Dim item As HandleErrorInfo = CType(Model, HandleErrorInfo)
        //To log error with Elmah
        Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(New Elmah.Error(Model.Exception, HttpContext.Current))
    End Code

<h2>
    Sorry, an error occurred while processing your request.<br />

    @item.ActionName<br />
    @item.ControllerName<br />
    @item.Exception.Message
</h2> 

Es simplemente!

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X