webentwicklung-frage-antwort-db.com.de

Protokollierungsfehler in ASP.NET MVC

Ich verwende derzeit log4net in meiner ASP.NET MVC-Anwendung, um Ausnahmen zu protokollieren. Ich mache das, indem ich alle meine Controller von einer BaseController-Klasse erben lasse. Im OnActionExecuting-Ereignis des BaseControllers protokolliere ich alle Ausnahmen, die möglicherweise aufgetreten sind:

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

Dies funktioniert hervorragend, wenn während einer Controller-Aktion eine nicht behandelte Ausnahme aufgetreten ist.

Was 404-Fehler betrifft, habe ich einen benutzerdefinierten Fehler in meiner web.config wie folgt eingerichtet:

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

Und in der Controller-Aktion, die die URL "Seite nicht gefunden" verarbeitet, protokolliere ich die angeforderte ursprüngliche URL:

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

    return View();
}

Und das funktioniert auch.

Das Problem, das ich habe, ist, wie man Fehler protokolliert, die auf den ASPX-Seiten selbst sind. Angenommen, ich habe einen Kompilierungsfehler auf einer der Seiten oder einen Inline-Code, der eine Ausnahme auslöst:

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

Es scheint, dass das HandleError-Attribut dies korrekt auf meine Error.aspx-Seite im freigegebenen Ordner umleitet, aber es wird definitiv nicht von der OnActionExecuted-Methode meines BaseController abgefangen. Ich dachte, ich könnte möglicherweise den Protokollierungscode auf der Seite Error.aspx selbst einfügen, bin mir aber nicht sicher, wie ich die Fehlerinformationen auf dieser Ebene abrufen soll.

106
Kevin Pang

Ich würde in Betracht ziehen, Ihre Webanwendung durch Einstecken von Elmah zu vereinfachen.

Sie fügen die Elmah Assembly Ihrem Projekt hinzu und konfigurieren dann Ihre web.config. Es werden dann Ausnahmen protokolliert, die auf Controller- oder Seitenebene erstellt wurden. Es kann so konfiguriert werden, dass es sich an verschiedenen Orten (wie SQL Server, E-Mail usw.) anmeldet. Es bietet auch ein Web-Frontend, mit dem Sie das Protokoll der Ausnahmen durchsuchen können.

Es ist das erste, was ich zu jeder asp.net mvc App hinzufüge, die ich erstelle.

Ich benutze immer noch log4net, aber ich neige dazu, es für die Protokollierung von Debug/Info zu verwenden und alle Ausnahmen Elmah zu überlassen.

Weitere Informationen finden Sie auch in der Frage Wie protokollieren Sie Fehler (Ausnahmen) in Ihren ASP.NET-Apps? .

99
Andrew Rimmer

Sie können das Ereignis OnError in der Datei Global.asax einbinden.

Etwas wie das:

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

    }


}
36
Chuck Conway

MVC3
Erstellen Sie ein Attribut, das von HandleErrorInfoAttribute erbt und die Protokollierung Ihrer Wahl enthält

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

Platzieren Sie das Attribut in Global.asax RegisterGlobalFilters

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

Haben Sie darüber nachgedacht, das HandleError-Attribut zu erweitern? Außerdem hat Scott einen guten Blog-Beitrag über Filter-Interceptors bei Controllern/Aktionen hier .

1
Kieron

Die Error.aspx-Ansicht ist folgendermaßen definiert:

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

Das HandleErrorInfo hat drei Eigenschaften: Zeichenfolge ActionName Zeichenfolge ControllerName Ausnahme Ausnahme

Sie sollten in der Lage sein, auf HandleErrorInfo und damit auf die Ausnahme in der Ansicht zuzugreifen.

1
Praveen Angyan

Sie können versuchen, HttpContext.Error zu untersuchen, aber ich bin nicht sicher.

0
Mike Chaliy