J'ai développé avec WebApi et suis passé à WebApi2 où Microsoft a introduit une nouvelle interface IHttpActionResult
qui semble recommandée pour le retour d'un HttpResponseMessage
. Je suis confus sur les avantages de cette nouvelle interface. Il semble fournir principalement juste un LÉGÈREMENT moyen plus facile de créer un HttpResponseMessage
.
Je dirais qu'il s'agit d'une "abstraction pour l'abstraction". Est-ce que je manque quelque chose? Quels sont les avantages réels de l’utilisation de cette nouvelle interface en plus de l’économie d’une ligne de code?
À l'ancienne (WebApi):
public HttpResponseMessage Delete(int id)
{
var status = _Repository.DeleteCustomer(id);
if (status)
{
return new HttpResponseMessage(HttpStatusCode.OK);
}
else
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
}
Nouvelle manière (WebApi2):
public IHttpActionResult Delete(int id)
{
var status = _Repository.DeleteCustomer(id);
if (status)
{
//return new HttpResponseMessage(HttpStatusCode.OK);
return Ok();
}
else
{
//throw new HttpResponseException(HttpStatusCode.NotFound);
return NotFound();
}
}
Vous pouvez décider de ne pas utiliser IHttpActionResult
car votre code existant génère un HttpResponseMessage
qui ne correspond à aucune des réponses prédéfinies. Vous pouvez cependant adapter HttpResponseMessage
à IHttpActionResult
en utilisant la réponse prédéfinie de ResponseMessage
. Il m'a fallu un certain temps pour comprendre cela, alors je voulais le poster pour montrer que vous ne devez pas nécessairement choisir l'un ou l'autre:
public IHttpActionResult SomeAction()
{
IHttpActionResult response;
//we want a 303 with the ability to set location
HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.RedirectMethod);
responseMsg.Headers.Location = new Uri("http://customLocation.blah");
response = ResponseMessage(responseMsg);
return response;
}
Remarque: ResponseMessage
est une méthode de la classe de base ApiController
dont votre contrôleur doit hériter.
Vous pouvez toujours utiliser HttpResponseMessage
. Cette capacité ne va pas disparaître. J'ai ressenti la même chose que vous et argumenté longuement avec l'équipe qu'il n'était pas nécessaire de recourir à une abstraction supplémentaire. Quelques arguments ont été avancés pour tenter de justifier son existence, mais rien ne m'a convaincu que cela en valait la peine.
C’est-à-dire jusqu’à ce que j’aie vu this échantillon de Brad Wilson . Si vous construisez des classes IHttpActionResult
d’une manière pouvant être chaînées, vous avez la possibilité de créer un pipeline de réponses "au niveau action" pour générer la HttpResponseMessage
. Sous les couvertures, c'est ainsi que ActionFilters
sont implémentés. Cependant, l'ordre de ces ActionFilters
n'est pas évident lors de la lecture de la méthode d'action, ce qui est une des raisons pour laquelle je ne suis pas fan des filtres d'action.
Cependant, en créant un IHttpActionResult
pouvant être explicitement chaîné dans votre méthode d'action, vous pouvez composer toutes sortes de comportements différents pour générer votre réponse.
Voici plusieurs avantages de IHttpActionResult
sur HttpResponseMessage
mentionnés dans documentation Microsoft ASP.Net :
- Simplifie les tests unitaires de vos contrôleurs.
- Déplace la logique commune pour la création de réponses HTTP dans des classes séparées.
- Rend l'intention de l'action du contrôleur plus claire en masquant les détails de bas niveau de la construction de la réponse.
Mais voici quelques autres avantages de l’utilisation de IHttpActionResult
à noter:
Ok
NotFound
Exception
Unauthorized
BadRequest
Conflict
Redirect
InvalidModelState
( lien vers la liste complète )ExecuteAsync
.ResponseMessageResult ResponseMessage(HttpResponseMessage response)
pour convertir HttpResponseMessage en IHttpActionResult .// this will return HttpResponseMessage as IHttpActionResult
return ResponseMessage(httpResponseMessage);
Ceci est juste mon opinion personnelle et les gens de l’équipe de l’API Web peuvent probablement mieux l’exprimer, mais voici mon 2c.
Tout d’abord, je pense que ce n’est pas une question de superposition. Vous pouvez les utiliser tous les deux en fonction de ce que vous voulez faire dans votre méthode d'action, mais pour comprendre le pouvoir réel de IHttpActionResult
, vous devrez probablement vous écarter de ces méthodes d'aide pratiques de ApiController
telles que Ok
, NotFound
, etc.
En gros, je pense à une classe implémentant IHttpActionResult
comme une usine de HttpResponseMessage
. Avec cet état d'esprit, il devient maintenant un objet à retourner et une usine qui le produit. En termes de programmation générale, vous pouvez créer l'objet vous-même dans certains cas et dans certains cas, vous avez besoin d'une usine pour le faire. Pareil ici.
Si vous souhaitez renvoyer une réponse qui doit être construite à l'aide d'une logique complexe, par exemple de nombreux en-têtes de réponse, etc., vous pouvez résumer toute cette logique dans une classe de résultat d'action implémentant IHttpActionResult
et l'utiliser dans plusieurs méthodes d'action. retour réponse.
L'utilisation de IHttpActionResult
comme type de retour présente un autre avantage: elle rend la méthode d'action de l'API Web ASP.NET similaire à MVC. Vous pouvez renvoyer n'importe quel résultat d'action sans vous faire attraper par les formateurs de média.
Bien sûr, comme l'a noté Darrel, vous pouvez chaîner les résultats des actions et créer un micro-pipeline puissant similaire aux gestionnaires de messages eux-mêmes dans le pipeline d'API. Vous aurez besoin de cela en fonction de la complexité de votre méthode d'action.
Longue histoire courte - ce n'est pas IHttpActionResult
versus HttpResponseMessage
. Fondamentalement, c'est comment vous voulez créer la réponse. Faites-le vous-même ou à travers une usine.
La Web API renvoie en gros 4 types d'objet: void
, HttpResponseMessage
, IHttpActionResult
et d'autres types forts. La première version de l'API Web renvoie HttpResponseMessage
, qui est un message de réponse HTTP assez simple.
La IHttpActionResult
a été introduite par WebAPI 2, qui est une sorte d’enveloppe de HttpResponseMessage
. Il contient la méthode ExecuteAsync()
pour créer un HttpResponseMessage
. Cela simplifie les tests unitaires de votre contrôleur.
Les autres types de retour sont des types de classes fortement typées sérialisées par l'API Web utilisant un formateur de média dans le corps de la réponse. L'inconvénient était que vous ne pouvez pas retourner directement un code d'erreur tel qu'un 404. Tout ce que vous pouvez faire, c'est de lancer une erreur HttpResponseException
.
Je préférerais implémenter la fonction d'interface TaskExecuteAsync pour IHttpActionResult. Quelque chose comme:
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = _request.CreateResponse(HttpStatusCode.InternalServerError, _respContent);
switch ((Int32)_respContent.Code)
{
case 1:
case 6:
case 7:
response = _request.CreateResponse(HttpStatusCode.InternalServerError, _respContent);
break;
case 2:
case 3:
case 4:
response = _request.CreateResponse(HttpStatusCode.BadRequest, _respContent);
break;
}
return Task.FromResult(response);
}
, où _request est HttpRequest et _respContent est la charge utile.
Nous avons les avantages suivants d’utiliser IHttpActionResult
sur HttpResponseMessage
:
IHttpActionResult
, nous nous concentrons uniquement sur les données à envoyer et non sur le code d'état. Donc ici le code sera plus propre et très facile à maintenir.async
et await
par défaut.