J'ai des inquiétudes sur la façon dont nous renvoyons les erreurs au client.
Renvoyons -nous l'erreur immédiatement en lançant HttpResponseException lorsque nous obtenons une erreur:
public void Post(Customer customer)
{
if (string.IsNullOrEmpty(customer.Name))
{
throw new HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
}
if (customer.Accounts.Count == 0)
{
throw new HttpResponseException("Customer does not have any account", HttpStatusCode.BadRequest)
}
}
Ou nous accumulons toutes les erreurs puis les renvoyons au client:
public void Post(Customer customer)
{
List<string> errors = new List<string>();
if (string.IsNullOrEmpty(customer.Name))
{
errors.Add("Customer Name cannot be empty");
}
if (customer.Accounts.Count == 0)
{
errors.Add("Customer does not have any account");
}
var responseMessage = new HttpResponseMessage<List<string>>(errors, HttpStatusCode.BadRequest);
throw new HttpResponseException(responseMessage);
}
Ce n'est qu'un exemple de code, peu importe les erreurs de validation ou les erreurs de serveur, j'aimerais simplement connaître les meilleures pratiques, les avantages et les inconvénients de chaque approche.
c#
rest
asp.net-web-api
cuongle
la source
la source
ModelState
.HttpResponseException
classe qui prend deux paramètres mentionnés dans votre message -HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
c'estHttpResponseException(string, HttpStatusCode)
Réponses:
Pour moi, je renvoie généralement un
HttpResponseException
et définit le code d'état en fonction de l'exception levée et si l'exception est fatale ou non, je déterminerai si je renvoieHttpResponseException
immédiatement.À la fin de la journée, c'est une API qui renvoie des réponses et non des vues, donc je pense que c'est bien de renvoyer un message avec le code d'exception et de statut au consommateur. Je n'ai actuellement pas besoin d'accumuler des erreurs et de les renvoyer car la plupart des exceptions sont généralement dues à des paramètres ou des appels incorrects, etc.
Un exemple dans mon application est que, parfois, le client demandera des données, mais qu'il n'y a pas de données disponibles, je lance une personnalisation
NoDataAvailableException
et la laisse bouillonner vers l'application Web API, où ensuite dans mon filtre personnalisé qui capture le renvoi d'un message pertinent avec le code d'état correct.Je ne suis pas sûr à 100% de la meilleure pratique pour cela, mais cela fonctionne pour moi actuellement, c'est donc ce que je fais.
Mise à jour :
Depuis que j'ai répondu à cette question, quelques articles de blog ont été écrits sur le sujet:
https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling
(celui-ci a de nouvelles fonctionnalités dans les versions nocturnes) https://docs.microsoft.com/archive/blogs/youssefm/error-handling-in-asp-net-webapi
Update 2
Mise à jour de notre processus de gestion des erreurs, nous avons deux cas:
Pour les erreurs générales telles que non trouvées ou les paramètres non valides transmis à une action, nous renvoyons un
HttpResponseException
pour arrêter immédiatement le traitement. De plus, pour les erreurs de modèle dans nos actions, nous remettrons le dictionnaire d'état du modèle à l'Request.CreateErrorResponse
extension et l'envelopperons dans aHttpResponseException
. L'ajout du dictionnaire d'état du modèle entraîne une liste des erreurs de modèle envoyées dans le corps de réponse.Pour les erreurs qui se produisent dans les couches supérieures, les erreurs de serveur, nous laissons la bulle d'exception à l'application Web API, nous avons ici un filtre d'exception global qui examine l'exception, la consigne avec ELMAH et essaie de donner un sens à la définition du HTTP correct code d'état et un message d'erreur convivial pertinent que le corps à nouveau dans un
HttpResponseException
. Pour les exceptions que nous n'attendons pas, le client recevra l'erreur de serveur interne 500 par défaut, mais un message générique pour des raisons de sécurité.Mise à jour 3
Récemment, après avoir récupéré l'API Web 2, pour renvoyer des erreurs générales, nous utilisons maintenant l' interface IHttpActionResult , en particulier les classes intégrées dans l'
System.Web.Http.Results
espace de noms telles que NotFound, BadRequest lorsqu'elles conviennent, si elles ne le font pas, nous les étendons, par exemple un résultat NotFound avec un message de réponse:la source
L'API Web ASP.NET 2 l'a vraiment simplifié. Par exemple, le code suivant:
renvoie le contenu suivant au navigateur lorsque l'élément est introuvable:
Suggestion: ne lancez pas l'erreur HTTP 500 sauf en cas d'erreur catastrophique (par exemple, exception de panne WCF). Choisissez un code d'état HTTP approprié qui représente l'état de vos données. (Voir le lien apigee ci-dessous.)
Liens:
la source
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
Quelle est la différence entreCreateResponse
etCreateErrorResponse
using System.Net.Http;
que laCreateResponse()
méthode d'extension apparaisse.Il semble que vous ayez plus de problèmes avec la validation que d'erreurs / exceptions, je vais donc en dire un peu sur les deux.
Validation
Les actions du contrôleur doivent généralement prendre des modèles d'entrée où la validation est déclarée directement sur le modèle.
Vous pouvez ensuite utiliser un
ActionFilter
qui renvoie automatiquement des messages de validation au client.Pour plus d'informations à ce sujet, consultez http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc
La gestion des erreurs
Il est préférable de renvoyer un message au client qui représente l'exception qui s'est produite (avec le code d'état correspondant).
Hors de la boîte que vous devez utiliser
Request.CreateErrorResponse(HttpStatusCode, message)
si vous souhaitez spécifier un message. Cependant, cela lie le code à l'Request
objet, ce que vous ne devriez pas avoir à faire.Je crée généralement mon propre type d'exception «sûre» que je suppose que le client saura comment gérer et envelopper tous les autres avec une erreur générique 500.
L'utilisation d'un filtre d'action pour gérer les exceptions ressemblerait à ceci:
Ensuite, vous pouvez l'enregistrer globalement.
Il s'agit de mon type d'exception personnalisé.
Un exemple d'exception que mon API peut lever.
la source
var exception = context.Exception as WebException;
qui était une faute de frappe, cela aurait dû l'êtreApiException
Vous pouvez lever une HttpResponseException
la source
Pour l'API Web 2, mes méthodes retournent systématiquement IHttpActionResult, donc j'utilise ...
la source
System.Net.Http
Si vous utilisez l'API Web ASP.NET 2, la méthode la plus simple consiste à utiliser la méthode courte ApiController. Cela se traduira par un BadRequestResult.
la source
return BadRequest(ModelState);
vous pouvez utiliser ActionFilter personnalisé dans Web Api pour valider le modèle
}
Enregistrez la classe CustomAttribute dans webApiConfig.cs config.Filters.Add (new DRFValidationFilters ());
la source
S'appuyant sur
Manish Jain
la réponse de (qui est destinée à Web API 2 qui simplifie les choses):1) Utilisez des structures de validation pour répondre à autant d'erreurs de validation que possible. Ces structures peuvent également être utilisées pour répondre à des demandes provenant de formulaires.
2) La couche de service renverra
ValidationResult
s, que l'opération réussisse ou non. Par exemple:3) Le contrôleur API construira la réponse en fonction du résultat de la fonction de service
Une option consiste à mettre pratiquement tous les paramètres en option et à effectuer une validation personnalisée qui renvoie une réponse plus significative. De plus, je prends soin de ne laisser aucune exception dépasser la limite de service.
la source
Utilisez la méthode intégrée "InternalServerError" (disponible dans ApiController):
la source
Juste pour mettre à jour l'état actuel d'ASP.NET WebAPI. L'interface est maintenant appelée
IActionResult
et l'implémentation n'a pas beaucoup changé:la source
Pour les erreurs où modelstate.isvalid est faux, j'envoie généralement l'erreur telle qu'elle est renvoyée par le code. C'est facile à comprendre pour le développeur qui consomme mon service. J'envoie généralement le résultat en utilisant le code ci-dessous.
Cela envoie l'erreur au client dans le format ci-dessous, qui est essentiellement une liste d'erreurs:
la source