2009-02-20 12 views
97

Attualmente sto utilizzando log4net nella mia applicazione ASP.NET MVC per registrare le eccezioni. Il modo in cui sto facendo questo è avere tutti i miei controller ereditati da una classe BaseController. Nel caso in OnActionExecuting del BaseController, annoto tutte le eccezioni che possono essersi verificati:Errori di registrazione in 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); 
    } 
} 

Questa grande opera se un'eccezione non gestita durante un'azione di controllo.

Per quanto riguarda i 404 errori, ho un errore personalizzato istituito nel mio web.config in questo modo:

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

E nella azione di controllo che gestisce l'url "page-not-found", accedo l'URL originale richiesto:

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

    return View(); 
} 

E questo funziona anche.

Il problema che sto avendo è come registrare gli errori che si trovano nelle pagine .aspx. Diciamo che ho un errore di compilazione su una delle pagine o qualche codice inline che un'eccezione:

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

Sembra che l'attributo HandleError sia correttamente Ricalcolo Con questo alla mia pagina Error.aspx nella cartella condivisa, ma sicuramente non viene catturato dal metodo OnActionExecuted del mio BaseController. Stavo pensando che potrei inserire il codice di registrazione nella pagina Error.aspx, ma non sono sicuro di come recuperare le informazioni sull'errore a quel livello.

+0

+1 per ELMAH. Ecco un [ELMAH Tutorial] (http://blog.elmah.io/elmah-tutorial/) che ho scritto per aiutarti a iniziare. Ricorda inoltre di utilizzare il pacchetto [Elmah.MVC] (https://www.nuget.org/packages/Elmah.MVC/) quando si utilizza ASP.NET MVC, per evitare problemi con pagine di errore personalizzate ecc. – ThomasArdal

+0

Ci sono alcuni prodotti là fuori che registrerà tutti gli errori che si verificano nelle app .NET. Non sono di livello così basso come ELMAH o log4net, ma ti fanno risparmiare un sacco di tempo se stai solo provando a monitorare e diagnosticare gli errori: [Bugsnag] (https://docs.bugsnag.com/platforms/dotnet/ asp-net /) e [AirBrake] (https://airbrake.io/languages/net_bug_tracker) sono due di quelli che conosco. NET –

risposta

96

Vorrei prendere in considerazione la semplificazione della vostra applicazione web collegando Elmah.

Si aggiunge l'assembly Elmah al progetto e quindi si configura web.config. Registrerà quindi le eccezioni create a livello di controller o di pagina. Può essere configurato per accedere a diversi luoghi (come SQL Server, Email ecc.). Fornisce inoltre un front-end Web, in modo che sia possibile sfogliare il registro delle eccezioni.

È la prima cosa che aggiungo a qualsiasi app di asp.net mvc che creo.

Uso ancora log4net, ma tendo ad usarlo per registrare debug/informazioni e lasciare tutte le eccezioni a Elmah.

È inoltre possibile trovare ulteriori informazioni nella domanda How do you log errors (Exceptions) in your ASP.NET apps?.

+3

Ho iniziato a utilizzare Elmah di recente ed è uno dei logger di eccezioni più chiari e semplici che ho mai usato. Ho letto un post che dice che MS dovrebbe includerlo in ASP.net e sono d'accordo. – dtc

+13

Perché ho bisogno sia di ELMAH che di log4net per l'app. registrazione? Perché non una singola soluzione? – VJAI

+0

Funzionerà anche se si dispone di un'architettura n-tier? Controller - servizi - repository? –

1

Si può provare ad esaminare HttpContext.Error, ma non sono sicuro su questo.

2

Hai mai pensato di estendere l'attributo HandleError? Inoltre, Scott ha un buon post sui filtri intercettori su controller/azioni here.

1

La vista Error.aspx viene definito in questo modo:

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

Il HandleErrorInfo ha tre proprietà: stringa ActionName stringa NomeControllore Exception Eccezione

Si dovrebbe essere in grado di accedere a HandleErrorInfo e quindi la Eccezione nella vista.

35

È possibile connettersi all'evento OnError in Global.asax.

Qualcosa di simile a questo:

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

Ciò dovrebbe catturare tutte le eccezioni. Considero questa la migliore pratica. –

+4

In base all'analisi del valore di ReSharper, 'Server' sarà sempre non nullo. –

+6

Ignorare 404 non ha funzionato per me nel modo in cui lo hai scritto. Ho scritto 'if (ex è HttpException && ((HttpException) ex) .GetHttpCode() == 404) return;' – pauloya

19

MVC3
Crea attributo che eredita da HandleErrorInfoAttribute e comprende la vostra scelta di registrazione

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

attributo posto in Global.asax RegisterGlobalFilters

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