Erreurs de journalisation ASP.NET MVC

j'utilise actuellement log4net dans mon ASP.NET MVC application to log exceptions. La façon dont je fais ça, c'est d'avoir tous mes contrôleurs hérités d'une classe de BaseController. Dans L'événement OnActionExecuting de BaseController, j'enregistre toutes les exceptions qui ont pu se produire:

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

cela fonctionne très bien si une exception s'est produite pendant une intervention du contrôleur.

comme pour les erreurs 404, j'ai une erreur personnalisée configurée dans mon web.config comme so:

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

et dans l'action du contrôleur qui gère l'url "page-not-found", j'enregistre l'url originale demandée:

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

    return View();
}

et ça marche aussi.

le problème que j'ai est comment enregistrer les erreurs qui sont sur le .aspx pages eux-mêmes. Disons que j'ai une erreur de compilation sur une des pages ou un code inline qui va jeter une exception:

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

il semble que L'attribut HandleError dévie correctement ceci de mon erreur.la page aspx dans le dossier partagé, mais elle n'est certainement pas capturée par la méthode OnActionExecuted de mon BaseController. Je pensais que je pourrais peut-être mettre le code de journalisation sur L'erreur.aspx page elle-même, mais je ne sais pas comment récupérer l'information d'erreur à ce niveau.

102
demandé sur Kevin Pang 2009-02-20 14:38:58

6 réponses

j'envisagerais de simplifier votre application web en branchant Elmah .

vous ajoutez L'assemblage D'Elmah à votre projet puis configurez votre web.config. Il enregistrera alors les exceptions créées au niveau du controller ou de la page. Il peut être configuré pour se connecter à différents endroits (comme SQL Server, Email etc). Il fournit également un frontend web, de sorte que vous pouvez parcourir le journal des exceptions.

C'est le premier ce que j'ajoute à tout asp.net MVC app I create.

j'utilise encore log4net, mais j'ai tendance à l'utiliser pour la journalisation de debug/info, et je laisse toutes les exceptions à Elmah.

vous pouvez également trouver plus d'informations dans la question comment enregistrez-vous les erreurs (Exceptions) dans votre ASP.NET applis? .

98
répondu Andrew Rimmer 2017-05-23 12:09:54

vous pouvez vous connecter à L'événement OnError dans le Global.asax.

quelque chose comme ça:

/// <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
répondu Chuck Conway 2009-03-09 06:59:43

MVC3

Créer L'attribut qui hérite de HandleErrorInfoAttribute et inclut votre choix de journalisation

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

attribut de Place dans Global.asax RegisterGlobalFilters

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
       // filters.Add(new HandleErrorAttribute());
        filters.Add(new ErrorLoggerAttribute());
    }
20
répondu Mark 2011-09-14 21:50:38

avez-vous pensé à étendre L'attribut HandleError? Aussi, Scott a un bon billet de blog sur les intercepteurs de filtre sur les contrôleurs / actions ici .

1
répondu Kieron 2009-02-20 12:17:51

L'Erreur.aspx view est défini comme suit:

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

le HandleErrorInfo a trois propriétés: string ActionName string ControllerName Exception Exception

vous devriez être en mesure d'accéder à HandleErrorInfo et donc L'Exception dans la vue.

1
répondu Praveen Angyan 2009-03-09 06:53:41

vous pouvez essayer d'examiner HttpContext.L'erreur, mais je ne suis pas sûr sur ce point.

0
répondu Mike Chaliy 2009-02-20 12:09:07