ASP.NET Web de Base de l'API de gestion des exceptions
J'ai commencé à utiliser ASP.NET de Base pour ma nouvelle API REST projet, après l'utilisation régulière ASP.NET l'API Web pour de nombreuses années. Je ne vois pas une bonne façon de gérer les exceptions dans ASP.NET de Base de l'API Web. J'ai essayé de mettre en œuvre la gestion des exceptions filtre/attribut:
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 Démarrage d'enregistrement de filtre:
services.AddMvc(options =>
{
options.Filters.Add(new AuthorizationFilter());
options.Filters.Add(new ErrorHandlingFilter());
});
Le problème j'ai eu, c'est que lorsque exception occurres dans mon AuthorizationFilter
c'est pas manipulé par ErrorHandlingFilter
. Je m'attendais à être pris comme il a travaillé avec de vieux ASP.NET l'API Web.
Alors, comment puis-je attraper toutes les exceptions de l'application ainsi que toutes les exceptions de l'Action des Filtres?
- Avez-vous essayé
UseExceptionHandler
middleware? - J'ai un exemple ici sur la façon d'utiliser
UseExceptionHandler
middleware
Vous devez vous connecter pour publier un commentaire.
La Gestion Des Exceptions Middleware
Après de nombreuses expériences avec différents exception de la manipulation des approches j'ai fini par utiliser un middleware. Il a travaillé sur le meilleur pour mon ASP.NET Web de Base de l'API de l'application. Il gère les exceptions de l'application, ainsi que les exceptions de l'action des filtres et j'ai le plein contrôle sur la gestion des exceptions et de la réponse HTTP. Voici mon traitement d'exception middleware:
Enregistrer avant MVC dans
Startup
classe:Vous pouvez ajouter de la trace de la pile d'exception de type nom, les codes d'erreur ou quoi que ce soit que vous voulez il. Très flexible. Voici un exemple d'exception réponse:
Injecter des
IOptions<MvcJsonOptions>
à laInvoke
méthode pour l'utiliser ensuite lors de la sérialisation de l'objet de réponse à utiliser ASP.NET MVC de sérialisation de paramètres dansJsonConvert.SerializeObject(errorObj, opts.Value.SerializerSettings)
pour mieux la sérialisation de la cohérence à travers tous les points de terminaison.Approche 2
Il y a un autre non-évident API appelée
UseExceptionHandler
qui fonctionne "ok" pour de simples scenarious:Ce n'est pas très évident, mais de configurer facilement la gestion des exceptions. Cependant, je préfère encore le middleware approche plus de ce que je reçois plus de contrôle avec la possibilité d'injecter des dépendances nécessaires.
await
tous vos appels asynchrones par exempleawait context.SaveChangesAsync();
. Il est difficile de deviner, sans voir le code. Je voudrais prendre un coup d'oeil si vous postez votre question avec plus de détails.IExceptionFilter
. Le filtre gère le contrôleur directement les erreurs, et j'utilise le middleware pour les plus "bas niveau" de la manipulation. Comme un soupçon, si quelqu'un a besoin d'exécuter du code par type d'exception dans le global gestionnaire, pour le rendre plus "lisible" n'hésitez pas à donner un coup d'oeil à une petite bibliothèque, je l'ai fait juste pour ça: medium.com/@nogravity00/...await next(context);
mais la pause surawait HandleExceptionAsync(context, ex);
. L'inspection du contexte, la réponse a un de 200 code. Je suis un peu perdu quant à pourquoi que l'exception a été levée, mais pas attrapé? Ne devrait-ce pas l'erreur d'être coincés ici?app.UseMiddleware<ErrorHandlingMiddleware>();
juste avantapp.UseStaticFiles();
. L'exception semble être pris correctement maintenant. Cela me mène à croireapp.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); app.UseBrowserLink();
Faire à l'interne de la magie middleware hackery pour obtenir le middleware de la commande de droite.context.Response.StatusCode == 404
dans la gestion des exceptions middleware et de réagir en tant que de besoin. Autres que ce cas, tous les les exceptions d'application sera pris dans le middleware. Espérons que cela aide.context.Response.StatusCode
à la ligneawait next(context)
est de 200 sur une mauvaise URL, pas de 404.await next(context);
comme MVC, à exécuter la première et de la condition définie par vous.NotFound
,BadRequest
etc. Mais pour les projets de production, même avec de simples n-tier de conception avec seulement 3 couches - contrôleurs, des services et des dépôts sera un énorme douleur. Dans certains de/la plupart des cas, vous pouvez obtenir loin de lui en retournantnull
à partir de la couche de service. Sinull
est une mauvaise pratique. Il n'y aurait nulle-vérifie partout. À l'aide d'exceptions est OK. Pas de null-chèques. Chute des performances n'est pas significatif et pour être honnête, je ferais le sacrifice de cette performance pour le code, d'une clarté toute la journée.Uppercase
les noms de propriété, tout en MVC faire aveclowercase
. C'est facilement réparable par le simple ajout d'unJsonSerializerSettings
avec unCamelCasePropertyNamesContractResolver
à laJsonConvert.SerializeObject(obj, settings)
appel.Votre meilleur pari est d'utiliser un Middleware pour atteindre la journalisation vous êtes à la recherche pour. Vous voulez mettre votre enregistrement d'exception dans un middleware et de gérer vos pages d'erreur affiché à l'utilisateur dans un autre middleware. Qui permet la séparation de la logique et suit le design de Microsoft a présenté, avec les 2 middleware entraînement. Voici un bon lien pour la documentation de Microsoft: La gestion des erreurs dans ASP.Net de Base
Pour votre exemple, vous souhaiterez peut-être utiliser une des extensions dans le StatusCodePage middleware ou rouler vos propres cette.
Vous pouvez trouver un exemple ici pour l'enregistrement des exceptions: ExceptionHandlerMiddleware.cs
Si vous n'aimez pas que la mise en œuvre spécifique, alors vous pouvez aussi utiliser ELM Middleware, et voici quelques exemples: Elm Exception Middleware
Si cela ne fonctionne pas pour vos besoins, vous pouvez toujours passer votre propre Middleware composant en regardant leurs implémentations de la ExceptionHandlerMiddleware et la ElmMiddleware de saisir les concepts pour la construction de votre propre.
Il est important d'ajouter la gestion d'exception middleware en dessous de la StatusCodePages middleware, mais au-dessus de tous les autres composants intergiciels. De cette façon, votre Exception middleware capture de l'exception, de l'enregistrer, puis de permettre à la demande de procéder à la StatusCodePage middleware qui permet d'afficher le message d'erreur de la page à l'utilisateur.
Dernière
Asp.Net Core
(à moins de 2.2, probablement plus tôt) est doté d'un middleware qui la rend un peu plus facile par rapport à la mise en œuvre dans l'acceptation réponse:Il doit faire à peu près la même chose, juste un peu moins de code à écrire. N'oubliez pas de l'ajouter avant de
UseMvc
que l'ordre est important.Pour Configurer le comportement de gestion des exceptions par type d'exception, vous pouvez utiliser un Middleware de packages NuGet:
pour
ASP.NET Core 2.0
ASP.NET Core 2.1+
.Exemple de Code:
Bien accepté réponse 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.
Selon ce lien j'ai eu une idée de faire de même. J'ai donc fusionné les Andreï Répondre avec ce. Donc mon code final est ci-dessous:
1. Classe de Base
2. Classe D'Exception Personnalisée De Type
3. Exception Personnalisée Middleware
4. Méthode D'Extension
5. Configurer la Méthode de démarrage.cs
Maintenant ma méthode d'ouverture de session dans le Compte du contrôleur :
Ci-dessus, vous pouvez voir si je n'ai pas trouvé l'utilisateur puis en soulevant le HttpStatusCodeException dans lequel j'ai passé HttpStatusCode.NotFound état et un message personnalisé
middleware
bloqué sera appelé, ce qui fera passer le contrôle
.
Mais que faire si j'ai eu d'erreur à l'exécution avant? Pour ce que j'ai utilisé essayez bloc catch qui jeter l'exception et sera piégé dans catch (Exception exceptionObj) de bloc et fera passer le contrôle
méthode.
J'ai utilisé un seul ErrorDetails classe pour l'uniformité.
startup.cs
dansvoid Configure(IapplicationBuilder app)
j'obtiens une erreurIApplicationBuilder does not contain a definition for ConfigureCustomExceptionMiddleware
. Et j'ai ajouté la référence, oùCustomExceptionMiddleware.cs
est.Tout d'abord, merci à Andrei comme je l'ai basé ma solution sur son exemple.
Je suis, y compris le mien, car c'est un exemple plus complet et peut enregistrer des lecteurs d'un certain temps.
La limitation de Andrei a une approche qui ne gèrent l'abattage, la capture potentiellement utile variables de requête et de la négociation de contenu (il sera toujours le retour JSON n'importe ce que le client a demandé - XML /texte etc).
Mon approche est d'utiliser un ObjectResult qui nous permet d'utiliser la fonctionnalité de boulangerie en MVC.
Ce code empêche également la mise en cache de la réponse.
La réponse d'erreur a été décoré de telle manière qu'il peut être sérialisé en XML sérialiseur.
Tout d'abord, configurez ASP.NET Core 2
Startup
pour ré-exécuter vers une page d'erreur pour les erreurs de du serveur web et les exceptions non gérées.Ensuite, définir un type d'exception qui vous permettra de générer des erreurs avec les codes d'état HTTP.
Enfin, dans votre contrôleur pour la page d'erreur, personnaliser la réponse basée sur la raison de l'erreur, et si la réponse va être perçu directement par un utilisateur final. Ce code suppose que toutes les API Url commencer avec
/api/
.ASP.NET Core journal les détails de l'erreur pour le débogage, donc un code de statut peut être tout ce que vous voulez offrir à un (potentiellement non fiables) demandeur. Si vous voulez montrer plus d'infos, vous pouvez améliorer
HttpException
à fournir. Pour les erreurs de l'API, vous pouvez mettre JSON codé erreur d'infos dans le corps du message en remplaçantreturn StatusCode...
avecreturn Json...
.