2009-02-20 24 views
97

Actualmente estoy usando log4net en mi aplicación ASP.NET MVC para registrar excepciones. La forma en que lo estoy haciendo es que todos mis controladores hereden de una clase BaseController. En caso OnActionExecuting del BaseController, entro las excepciones que puedan haber ocurrido:Errores de registro en ASP.NET MVC

protected override void OnActionExecuted(ActionExecutedContext filterContext) 
{ 
    // Log any exceptions 
    ILog log = LogManager.GetLogger(filterContext.Controller.GetType()); 

    if (filterContext.Exception != null) 
    { 
     log.Error("Unhandled exception: " + filterContext.Exception.Message + 
      ". Stack trace: " + filterContext.Exception.StackTrace, 
      filterContext.Exception); 
    } 
} 

Esto funciona muy bien si una excepción no controlada durante una acción del controlador.

En cuanto a los errores 404, tengo un error personalizado creado en mi web.config de este modo:

<customErrors mode="On"> 
    <error statusCode="404" redirect="~/page-not-found"/> 
</customErrors> 

Y en la acción del controlador que maneja la url "página no encontrado", me conecto la URL original solicitada:

[AcceptVerbs(HttpVerbs.Get)] 
public ActionResult PageNotFound() 
{ 
    log.Warn("404 page not found - " + Utils.SafeString(Request.QueryString["aspxerrorpath"])); 

    return View(); 
} 

Y esto también funciona.

El problema que tengo es cómo registrar los errores que están en las páginas .aspx. Digamos que tengo un error de compilación en una de las páginas o algún código en línea que va a lanzar una excepción:

<% ThisIsNotAValidFunction(); %> 
<% throw new Exception("help!"); %> 

Parece ser que el atributo HandleError está redireccionando correctamente esto a mi página Error.aspx en la carpeta compartida, pero definitivamente no está siendo capturado por el método OnActionExecuted de mi BaseController. Pensaba que podría poner el código de registro en la página Error.aspx, pero no estoy seguro de cómo recuperar la información de error en ese nivel.

+0

+1 para ELMAH. Aquí hay un [Tutorial de ELMAH] (http://blog.elmah.io/elmah-tutorial/) Lo escribí para ayudarlo a comenzar. Recuerde también utilizar el paquete [Elmah.MVC] (https://www.nuget.org/packages/Elmah.MVC/) cuando utilice ASP.NET MVC, para evitar problemas con páginas de error personalizadas, etc. – ThomasArdal

+0

Hay algunos productos por ahí que registrará todos los errores que ocurren en las aplicaciones .NET. No son tan de bajo nivel como ELMAH o log4net, pero le ahorran un montón de tiempo si solo está tratando de monitorear y diagnosticar errores: [Bugsnag] (https://docs.bugsnag.com/platforms/dotnet/ asp-net /) y [AirBrake] (https://airbrake.io/languages/net_bug_tracker) son dos de los que conozco .NET –

Respuesta

96

Consideraría simplificar su aplicación web conectando Elmah.

Agregue el ensamblaje Elmah a su proyecto y luego configure su web.config. A continuación, registrará las excepciones creadas en el controlador o en el nivel de la página. Se puede configurar para iniciar sesión en varios lugares diferentes (como SQL Server, correo electrónico, etc.). También proporciona una interfaz web, para que pueda navegar a través del registro de excepciones.

Es lo primero que agrego a cualquier aplicación asp.net mvc que creo.

Todavía uso log4net, pero tiendo a usarlo para registrar depuración/información, y dejar todas las excepciones a Elmah.

También puede encontrar más información en la pregunta How do you log errors (Exceptions) in your ASP.NET apps?.

+3

Comencé a utilizar Elmah recientemente y es uno de los registradores de excepciones más hábiles y sencillos que he alguna vez usado. Leí una publicación diciendo que MS debería incluirla en ASP.net y acepto. – dtc

+13

Por qué necesito tanto ELMAH como log4net para la aplicación. ¿explotación florestal? ¿Por qué no una sola solución? – VJAI

+0

¿Funcionará esto incluso si tengo arquitectura n-tier? Controladores - servicios - repositorios? –

1

Puede intentar examinar HttpContext.Error, pero no estoy seguro de esto.

2

¿Ha pensado en ampliar el atributo HandleError? Además, Scott tiene una buena publicación de blog sobre interceptores de filtro en controladores/acciones here.

1

La vista Error.aspx se define así:

namespace MvcApplication1.Views.Shared 
{ 
    public partial class Error : ViewPage<HandleErrorInfo> 
    { 
    } 
} 

El HandleErrorInfo tiene tres propiedades: cadena ActionName cadena ControllerName Excepción Excepción

Usted debe ser capaz de acceder y por lo tanto la HandleErrorInfo Excepción dentro de la vista.

35

Puede enganchar en el evento OnError en Global.asax.

Algo como esto:

/// <summary> 
/// Handles the Error event of the Application control. 
/// </summary> 
/// <param name="sender">The source of the event.</param> 
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> 
protected void Application_Error(object sender, EventArgs e) 
{ 
    if (Server != null) 
    { 
     Exception ex = Server.GetLastError(); 

     if (Response.StatusCode != 404) 
     { 
      Logging.Error("Caught in Global.asax", ex); 
     } 

    } 


} 
+2

Esto debería capturar todas las excepciones. Considero que esta es la mejor práctica. –

+4

De acuerdo con el análisis de valor de ReSharper, 'Servidor' siempre será no nulo. –

+6

Haciendo caso omiso de 404 no funcionó para mí la forma en que lo escribió. Escribí 'if (ex es HttpException && ((HttpException) ex) .GetHttpCode() == 404) return;' – pauloya

19

MVC3
Crear atributo que hereda de HandleErrorInfoAttribute e incluye su opción de registro

public class ErrorLoggerAttribute : HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext filterContext) 
    { 
     LogError(filterContext); 
     base.OnException(filterContext); 
    } 

    public void LogError(ExceptionContext filterContext) 
    { 
     // You could use any logging approach here 

     StringBuilder builder = new StringBuilder(); 
     builder 
      .AppendLine("----------") 
      .AppendLine(DateTime.Now.ToString()) 
      .AppendFormat("Source:\t{0}", filterContext.Exception.Source) 
      .AppendLine() 
      .AppendFormat("Target:\t{0}", filterContext.Exception.TargetSite) 
      .AppendLine() 
      .AppendFormat("Type:\t{0}", filterContext.Exception.GetType().Name) 
      .AppendLine() 
      .AppendFormat("Message:\t{0}", filterContext.Exception.Message) 
      .AppendLine() 
      .AppendFormat("Stack:\t{0}", filterContext.Exception.StackTrace) 
      .AppendLine(); 

     string filePath = filterContext.HttpContext.Server.MapPath("~/App_Data/Error.log"); 

     using(StreamWriter writer = File.AppendText(filePath)) 
     { 
      writer.Write(builder.ToString()); 
      writer.Flush(); 
     } 
    } 

Lugar atributo en Global.asax RegisterGlobalFilters

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     // filters.Add(new HandleErrorAttribute()); 
     filters.Add(new ErrorLoggerAttribute()); 
    } 
Cuestiones relacionadas