J'utilise ASP.NET Core pour mon nouveau projet d'API REST après avoir utilisé l'API Web ASP.NET régulière pendant de nombreuses années. Je ne vois aucun bon moyen de gérer les exceptions dans l'API Web ASP.NET Core. J'ai essayé d'implémenter un filtre / attribut de gestion des exceptions:
public class ErrorHandlingFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
HandleExceptionAsync(context);
context.ExceptionHandled = true;
}
private static void HandleExceptionAsync(ExceptionContext context)
{
var exception = context.Exception;
if (exception is MyNotFoundException)
SetExceptionResult(context, exception, HttpStatusCode.NotFound);
else if (exception is MyUnauthorizedException)
SetExceptionResult(context, exception, HttpStatusCode.Unauthorized);
else if (exception is MyException)
SetExceptionResult(context, exception, HttpStatusCode.BadRequest);
else
SetExceptionResult(context, exception, HttpStatusCode.InternalServerError);
}
private static void SetExceptionResult(
ExceptionContext context,
Exception exception,
HttpStatusCode code)
{
context.Result = new JsonResult(new ApiResponse(exception))
{
StatusCode = (int)code
};
}
}
Et voici mon enregistrement de filtre de démarrage:
services.AddMvc(options =>
{
options.Filters.Add(new AuthorizationFilter());
options.Filters.Add(new ErrorHandlingFilter());
});
Le problème que je rencontrais est que lorsque des exceptions se produisent dans mon, AuthorizationFilter
il n'est pas géré par ErrorHandlingFilter
. Je m'attendais à ce qu'il soit pris là comme il fonctionnait avec l'ancienne API Web ASP.NET.
Alors, comment puis-je intercepter toutes les exceptions d'application ainsi que toutes les exceptions des filtres d'action?
c#
exception
asp.net-core
Andrei
la source
la source
UseExceptionHandler
middleware?UseExceptionHandler
middlewareRéponses:
Middleware de gestion des exceptions
Après de nombreuses expériences avec différentes approches de gestion des exceptions, j'ai fini par utiliser un middleware. Il a fonctionné le mieux pour mon application API Web ASP.NET Core. Il gère les exceptions d'application ainsi que les exceptions des filtres d'action et j'ai un contrôle total sur la gestion des exceptions et la réponse HTTP. Voici mon exception de gestion des middlewares:
Enregistrez-le avant MVC en
Startup
classe:Vous pouvez ajouter une trace de pile, un nom de type d'exception, des codes d'erreur ou tout ce que vous voulez. Très souple. Voici un exemple de réponse d'exception:
Pensez à injecter
IOptions<MvcJsonOptions>
dans laInvoke
méthode pour ensuite l'utiliser lorsque vous sérialisez l'objet de réponse pour utiliser les paramètres de sérialisation d'ASP.NET MVCJsonConvert.SerializeObject(errorObj, opts.Value.SerializerSettings)
pour une meilleure cohérence de sérialisation sur tous les points de terminaison.Approche 2
Il existe une autre API non évidente appelée
UseExceptionHandler
qui fonctionne "ok" pour des scénarios simples:Ce n'est pas un moyen très évident mais facile de configurer la gestion des exceptions. Cependant, je préfère toujours l'approche middleware, car j'obtiens plus de contrôle avec la possibilité d'injecter les dépendances nécessaires.
la source
app.UseMiddleware<ErrorHandlingMiddleware>();
juste avantapp.UseStaticFiles();
. L'exception semble être interceptée correctement maintenant. Cela m'amène à croire queapp.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); app.UseBrowserLink();
vous devez faire du piratage de middleware magique interne pour obtenir le bon ordre du middleware.Le dernier
Asp.Net Core
(au moins de 2.2, probablement plus tôt) a un middleware intégré qui le rend un peu plus facile par rapport à l'implémentation dans la réponse acceptée:Il devrait faire à peu près la même chose, juste un peu moins de code à écrire.
Important: N'oubliez pas de l'ajouter avant
UseMvc
(ouUseRouting
dans .Net Core 3) car l'ordre est important.la source
Votre meilleur pari est d'utiliser un middleware pour obtenir la journalisation que vous recherchez. Vous souhaitez placer votre journalisation des exceptions dans un middleware, puis gérer vos pages d'erreur affichées pour l'utilisateur dans un middleware différent. Cela permet de séparer la logique et suit la conception que Microsoft a conçue avec les 2 composants middleware. Voici un bon lien vers la documentation de Microsoft: Gestion des erreurs dans ASP.Net Core
Pour votre exemple spécifique, vous souhaiterez peut-être utiliser l'une des extensions du middleware StatusCodePage ou lancer la vôtre comme ceci .
Vous pouvez trouver un exemple ici pour la journalisation des exceptions: ExceptionHandlerMiddleware.cs
Si vous n'aimez pas cette implémentation spécifique, vous pouvez également utiliser ELM Middleware , et voici quelques exemples: Elm Exception Middleware
Si cela ne fonctionne pas pour vos besoins, vous pouvez toujours lancer votre propre composant Middleware en regardant leurs implémentations d'ExceptionHandlerMiddleware et ElmMiddleware pour saisir les concepts pour construire le vôtre.
Il est important d'ajouter le middleware de gestion des exceptions sous le middleware StatusCodePages mais surtout vos autres composants middleware. De cette façon, votre middleware Exception capturera l'exception, l'enregistrera, puis permettra à la requête de passer au middleware StatusCodePage qui affichera la page d'erreur conviviale à l'utilisateur.
la source
UseStatusCodePages
soit utile dans les implémentations de service d'API Web. Aucune vue ou HTML du tout, seulement des réponses JSON ...Une réponse bien acceptée m'a beaucoup aidé mais je voulais passer HttpStatusCode dans mon middleware pour gérer le code d'état d'erreur lors de l'exécution.
D'après ce lien, j'ai eu l'idée de faire de même. J'ai donc fusionné la réponse Andrei avec cela. Donc, mon code final est ci-dessous:
1. Classe de base
2. Type de classe d'exception personnalisée
3. Middleware d'exception personnalisé
4. Méthode d'extension
5. Configurer la méthode dans startup.cs
Maintenant, ma méthode de connexion dans le contrôleur de compte:
Ci-dessus, vous pouvez voir si je n'ai pas trouvé l'utilisateur, puis lever l'exception HttpStatusCodeException dans laquelle j'ai passé le statut HttpStatusCode.NotFound et un message personnalisé
dans le middleware
bloqué sera appelé qui passera le contrôle à
.
Mais que faire si j'ai eu une erreur d'exécution avant? Pour cela, j'ai utilisé un bloc try catch qui lève une exception et sera pris dans le bloc catch (Exception exceptionObj) et passera le contrôle à
méthode.
J'ai utilisé une seule classe ErrorDetails pour l'uniformité.
la source
startup.cs
envoid Configure(IapplicationBuilder app)
je reçois une erreurIApplicationBuilder does not contain a definition for ConfigureCustomExceptionMiddleware
. Et j'ai ajouté la référence, oùCustomExceptionMiddleware.cs
est.Pour configurer le comportement de gestion des exceptions par type d'exception, vous pouvez utiliser le middleware des packages NuGet:
ASP.NET Core 2.0
ASP.NET Core 2.1+
.Échantillon de code:
la source
Tout d'abord, merci à Andrei car j'ai basé ma solution sur son exemple.
J'inclus le mien car c'est un échantillon plus complet et cela pourrait faire gagner du temps aux lecteurs.
La limite de l'approche d'Andrei est qu'elle ne gère pas la journalisation, la capture de variables de requête potentiellement utiles et la négociation de contenu (elle renverra toujours JSON, peu importe ce que le client a demandé - XML / texte brut, etc.).
Mon approche consiste à utiliser un ObjectResult qui nous permet d'utiliser la fonctionnalité intégrée à MVC.
Ce code empêche également la mise en cache de la réponse.
La réponse d'erreur a été décorée de manière à pouvoir être sérialisée par le sérialiseur XML.
la source
Tout d'abord, configurez ASP.NET Core 2
Startup
pour qu'il s'exécute à nouveau sur une page d'erreur pour toutes les erreurs du serveur Web et toutes les exceptions non gérées.Ensuite, définissez un type d'exception qui vous permettra de générer des erreurs avec des codes d'état HTTP.
Enfin, dans votre contrôleur pour la page d'erreur, personnalisez la réponse en fonction de la raison de l'erreur et si la réponse sera vue directement par un utilisateur final. Ce code suppose que toutes les URL d'API commencent par
/api/
.ASP.NET Core enregistrera les détails de l'erreur pour que vous puissiez déboguer, donc un code d'état peut être tout ce que vous voulez fournir à un demandeur (potentiellement non fiable). Si vous souhaitez afficher plus d'informations, vous pouvez les améliorer
HttpException
pour les fournir. Pour les erreurs d'API, vous pouvez mettre des informations d'erreur codées JSON dans le corps du message en les remplaçantreturn StatusCode...
parreturn Json...
.la source
utiliser un middleware ou IExceptionHandlerPathFeature est très bien. il y a une autre façon dans eshop
créer un filtre d'exception et l'enregistrer
la source