124 votes

attraper toutes les exceptions non gérées dans ASP.NET Web Api

Comment puis-je attraper todo les exceptions non gérées qui se produisent dans ASP.NET Web Api afin que je puisse les consigner ?

Jusqu'à présent, j'ai essayé :

  • Créer et enregistrer un ExceptionHandlingAttribute
  • Mettre en œuvre un Application_Error méthode dans Global.asax.cs
  • S'abonner à AppDomain.CurrentDomain.UnhandledException
  • S'abonner à TaskScheduler.UnobservedTaskException

El ExceptionHandlingAttribute traite avec succès les exceptions qui sont lancées dans les méthodes d'action et les filtres d'action du contrôleur, mais d'autres exceptions ne sont pas traitées, par exemple :

  • Exceptions déclenchées lorsqu'une IQueryable retourné par une méthode d'action ne s'exécute pas
  • Les exceptions lancées par un gestionnaire de messages (c'est-à-dire HttpConfiguration.MessageHandlers )
  • Exceptions lancées lors de la création d'une instance de contrôleur

En gros, si une exception doit entraîner le renvoi d'une erreur de serveur interne 500 au client, je veux qu'elle soit enregistrée. Mise en œuvre de Application_Error Ce travail a bien fonctionné dans Web Forms et MVC - que puis-je utiliser dans Web Api ?

0 votes

Avez-vous essayé d'utiliser Surveillance de la santé d'ASP.NET ? Activez-la et voyez si vos exceptions ne sont pas enregistrées dans le journal des événements.

0 votes

La surveillance de la santé détecte les exceptions de mon pipeline MVC, mais pas celles de mon pipeline Web Api.

0 votes

Merci - Il m'a fallu un certain temps pour comprendre pourquoi je ne pouvais pas enregistrer mes problèmes de constructeur / d'injection de dépendances, alors que je pensais que l'enregistrement WebAPI était déjà réglé...

163voto

decates Points 368

Cela est désormais possible avec WebAPI 2.1 (voir l Quoi de neuf ):

Créez une ou plusieurs implémentations de IExceptionLogger. Par exemple :

public class TraceExceptionLogger : ExceptionLogger
{
    public override void Log(ExceptionLoggerContext context)
    {
        Trace.TraceError(context.ExceptionContext.Exception.ToString());
    }
}

Ensuite, enregistrez-la avec la configuration Http de votre application, dans un appel de configuration, comme suit :

config.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());

ou directement :

GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());

7 votes

@NeilBarnwell Oui, l'API Web 2.1 correspond à la version de l'assemblage System.Web.Http 5.1.0 . Vous avez donc besoin de cette version ou d'une version supérieure pour utiliser la solution décrite ici. Voir les versions des paquets nuget

4 votes

Certaines erreurs 500 ne sont toujours pas prises en compte, par exemple HttpException - l'hôte distant a fermé la connexion. Y a-t-il encore une place pour global.asax Application_Error pour gérer les erreurs en dehors du traitement de l'api web ?

13 votes

J'adore à quel point la doco officielle est détaillée sur msdn et ce que 99% des développeurs veulent vraiment, c'est juste les 8 lignes de code pour enregistrer les erreurs.

21voto

Duoc Tran Points 755

La réponse de Yuval est destinée à personnaliser les réponses aux exceptions non gérées par l'API Web, et non à la journalisation, comme indiqué sur le lien suivant page . Reportez-vous à la section "Quand utiliser" de la page pour plus de détails. Le logger est toujours appelé mais le handler n'est appelé que lorsqu'une réponse peut être envoyée. En bref, utilisez le bûcheron pour enregistrer et le gestionnaire pour personnaliser la réponse.

Au fait, j'utilise la version 5.2.3 d'Assemblage et le logiciel ExceptionHandler ne dispose pas de la classe HandleCore méthode. L'équivalent, je pense, est Handle . Cependant, le simple fait de sous-classer ExceptionHandler (comme dans la réponse de Yuval) ne fonctionne pas. Dans mon cas, je dois implémenter IExceptionHandler comme suit.

internal class OopsExceptionHandler : IExceptionHandler
{
    private readonly IExceptionHandler _innerHandler;

    public OopsExceptionHandler (IExceptionHandler innerHandler)
    {
        if (innerHandler == null)
            throw new ArgumentNullException(nameof(innerHandler));

        _innerHandler = innerHandler;
    }

    public IExceptionHandler InnerHandler
    {
        get { return _innerHandler; }
    }

    public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
    {
        Handle(context);

        return Task.FromResult<object>(null);
    }

    public void Handle(ExceptionHandlerContext context)
    {
        // Create your own custom result here...
        // In dev, you might want to null out the result
        // to display the YSOD.
        // context.Result = null;
        context.Result = new InternalServerErrorResult(context.Request);
    }
}

Notez que, contrairement au logger, vous enregistrez votre gestionnaire en remplaçant le gestionnaire par défaut, et non en l'ajoutant.

config.Services.Replace(typeof(IExceptionHandler),
    new OopsExceptionHandler(config.Services.GetExceptionHandler()));

21voto

Joe Daley Points 9352

Pour répondre à ma propre question, ce n'est pas possible !

La gestion de toutes les exceptions qui provoquent des erreurs de serveur interne semble être une capacité de base que l'API Web devrait avoir. J'ai donc demandé à Microsoft d'ajouter une fonction de gestion des exceptions à l'API Web. Gestionnaire d'erreurs global pour l'API Web :

https://aspnetwebstack.codeplex.com/workitem/1001

Si vous êtes d'accord, allez sur ce lien et votez pour lui !

En attendant, l'excellent article Traitement des exceptions de l'API Web ASP.NET montre quelques façons différentes d'attraper quelques catégories d'erreurs différentes. C'est plus compliqué que cela ne devrait l'être, et cela ne permet pas d'attraper todo des erreurs de serveur intercalaires, mais c'est la meilleure approche disponible aujourd'hui.

Mise à jour : La gestion des erreurs globales est maintenant implémentée et disponible dans les nightly builds ! Il sera publié dans ASP.NET MVC v5.1. Voici comment cela fonctionnera : https://aspnetwebstack.codeplex.com/wikipage?title=Global%20Error%20Handling

0 votes

Cela semble être une raison d'utiliser un contrôleur pour les appels ajax plutôt qu'une api web. les limites sont déjà floues. mais si ELMAH est capable de le capturer, il y a peut-être une solution.

4 votes

La gestion des erreurs globales a été ajoutée dans l'API Web 2.1. Voir ma réponse pour plus de détails.

11voto

Yuval Itzchakov Points 13820

Vous pouvez également créer un gestionnaire d'exception global en implémentant l'option IExceptionHandler (ou hériter de l'interface ExceptionHandler classe de base). Elle sera la dernière à être appelée dans la chaîne d'exécution, après tout ce qui a été enregistré. IExceptionLogger :

L'IExceptionHandler gère toutes les exceptions non gérées de tous les contrôleurs. contrôleurs. C'est le dernier de la liste. Si une exception se produit, le IExceptionLogger sera appelé en premier, puis le contrôleur ExceptionFilters du contrôleur et, si elle n'est toujours pas gérée, l'implémentation IExceptionHandler implémentation.

public class OopsExceptionHandler : ExceptionHandler
{
    public override void HandleCore(ExceptionHandlerContext context)
    {
        context.Result = new TextPlainErrorResult
        {
            Request = context.ExceptionContext.Request,
            Content = "Oops! Sorry! Something went wrong."        
        };
    }

    private class TextPlainErrorResult : IHttpActionResult
    {
        public HttpRequestMessage Request { get; set; }

        public string Content { get; set; }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            HttpResponseMessage response = 
                             new HttpResponseMessage(HttpStatusCode.InternalServerError);
            response.Content = new StringContent(Content);
            response.RequestMessage = Request;
            return Task.FromResult(response);
        }
    }
}

Plus d'informations à ce sujet aquí .

1voto

Pablo Cibraro Points 1714

Vous pouvez utiliser l'infrastructure de traçage pour consigner les exceptions. J'ai abordé cette approche dans cet article de blog,

http://weblogs.asp.net/cibrax/archive/2013/03/01/asp-net-web-api-logging-and-troubleshooting.aspx

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X