339 votes

Pourquoi devrais-je utiliser IHttpActionResult au lieu de HttpResponseMessage?

J'ai développé avec WebApi et suis passé à WebApi2 où Microsoft a introduit une nouvelle interface IHttpActionResult qui semble être recommandée à utiliser plutôt que de retourner un HttpResponseMessage. Je suis confus quant aux avantages de cette nouvelle interface. Il semble principalement offrir un moyen LÉGÈREMENT plus facile de créer un HttpResponseMessage.

Je dirais que c'est de "l'abstraction pour l'abstraction". Est-ce que je rate quelque chose? Quels sont les avantages réels que j'obtiens en utilisant cette nouvelle interface, à part peut-être économiser une ligne de code?

Ancienne méthode (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 méthode (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();
    }
}

1 votes

Je viens de trouver quelque chose d'intéressant. Je ne suis pas sûr si ces résultats peuvent être vérifiés par quelqu'un d'autre. Mais les performances ont beaucoup amélioré avec quelques appels que j'ai faits : * Avec un exemple utilisant HttpResponseMessage j'ai reçu la réponse en 9545 ms. * Utilisant le IHttpActionResult j'ai reçu la même réponse en 294 ms.

0 votes

@chrislesage 9545 ms représente presque 10 secondes. Même 294ms est assez lent. Si quelque chose prend plus de 100ms alors quelque chose d'autre est en jeu là. Il y a plus dans cette histoire qu'il n'y paraît.

318voto

AaronLS Points 12720

Vous pourriez décider de ne pas utiliser IHttpActionResult car votre code existant construit un HttpResponseMessage qui ne correspond pas à l'une des réponses pré-enregistrées. Cependant, vous pouvez adapter HttpResponseMessage à IHttpActionResult en utilisant la réponse prédéfinie de ResponseMessage. Ça m'a pris un certain temps pour comprendre cela, donc je voulais le poster en montrant que vous n'êtes pas nécessairement obligé de choisir l'un ou l'autre :

public IHttpActionResult SomeAction()
{
   IHttpActionResult response;
   //nous voulons un 303 avec la possibilité de définir l'emplacement
   HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.RedirectMethod);
   responseMsg.Headers.Location = new Uri("http://customLocation.blah");
   response = ResponseMessage(responseMsg);
   return response;
}

Notez que ResponseMessage est une méthode de la classe de base ApiController que votre contrôleur doit hériter.

1 votes

Il m'a fallu un certain temps pour découvrir que ResponseMessage est maintenant ResponseMessageResult. Peut-être a-t-il été renommé récemment? P.S. Vous avez également omis un nouveau mot-clé dans la réponse et merci beaucoup pour la suggestion :)

10 votes

@IlyaChernomordik ResponseMessage et ResponseMessageResult sont deux choses différentes. ResponseMessage() est une méthode de ApiController dont votre contrôleur devrait hériter, et donc c'est juste un appel de méthode. Donc, aucun mot-clé new n'est nécessaire ici. Vous n'héritez probablement pas de ApiController ou vous êtes à l'intérieur d'une méthode statique. ResponseMessageResult est le type de retour de ResponseMessage().

3 votes

@IlyaChernomordik J'aurais pu écrire response = base.ResponseMessage(responseMsg) pour indiquer plus clairement qu'il s'agit d'une méthode de la classe de base ApiController

85voto

Darrel Miller Points 56797

Vous pouvez toujours utiliser HttpResponseMessage. Cette fonctionnalité ne disparaîtra pas. J'ai ressenti la même chose que vous et j'ai beaucoup discuté avec l'équipe qu'il n'était pas nécessaire d'ajouter une abstraction supplémentaire. Il y a eu quelques arguments avancés pour justifier son existence mais rien ne m'a convaincue que cela en valait la peine.

C'est, jusqu'à ce que je vois ceci exemple de Brad Wilson. Si vous construisez des classes IHttpActionResult de manière à pouvoir les enchaîner, vous gagnez la capacité de créer un pipeline de réponse au niveau de l'"action" pour générer le HttpResponseMessage. Sous-jacent, c'est ainsi que les ActionFilters sont implémentés cependant, l'ordre de ces ActionFilters n'est pas évident en lisant la méthode d'action, ce qui est une raison pour laquelle je ne suis pas fan des filtres d'action.

Cependant, en créant un IHttpActionResult pouvant être enchaîné de manière explicite dans votre méthode d'action, vous pouvez composer toutes sortes de comportements différents pour générer votre réponse.

64voto

Behzad Bahmanyar Points 3332

Voici plusieurs avantages de IHttpActionResult par rapport à HttpResponseMessage mentionnés dans la documentation Microsoft ASP.Net:

  • Simplifie les tests unitaires de vos contrôleurs.
  • Déplace la logique commune de création des 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 d'autres avantages de l'utilisation de IHttpActionResult qui méritent d'être mentionnés :

  • Respect du principe de responsabilité unique : les méthodes d'action ont la responsabilité de servir les demandes HTTP et ne les impliquent pas dans la création des messages de réponse HTTP.
  • Implémentations utiles déjà définies dans System.Web.Http.Results, à savoir : Ok NotFound Exception Unauthorized BadRequest Conflict Redirect InvalidModelState (lien vers la liste complète)
  • Utilise Async et Await par défaut.
  • Facile à créer votre propre ActionResult simplement en implémentant la méthode ExecuteAsync.
  • Vous pouvez utiliser ResponseMessageResult ResponseMessage(HttpResponseMessage response) pour convertir HttpResponseMessage en IHttpActionResult.

34voto

Adam Tal Points 2094
// cela renverra HttpResponseMessage en tant qu'IHttpActionResult
return ResponseMessage(httpResponseMessage);

18voto

Badri Points 7046

Ceci est juste mon opinion personnelle et les gens de l'équipe API Web peuvent probablement l'articuler mieux, mais voici mon avis.

Tout d'abord, je pense que ce n'est pas une question de l'un par rapport à l'autre. Vous pouvez les utiliser tous les deux en fonction de ce que vous voulez faire dans votre méthode d'action mais pour comprendre la véritable puissance de IHttpActionResult, vous aurez probablement besoin de sortir de ces méthodes d'aide pratiques de ApiController telles que Ok, NotFound, etc.

Fondamentalement, je pense qu'une classe implémentant IHttpActionResult est une usine de HttpResponseMessage. Avec cette approche, cela devient maintenant un objet qui doit être renvoyé et une usine qui le produit. Dans un sens de programmation général, vous pouvez créer l'objet vous-même dans certains cas et dans d'autres cas, vous avez besoin d'une usine pour le faire. Même chose ici.

Si vous voulez renvoyer une réponse qui doit être construite à travers une logique complexe, disons beaucoup d'en-têtes de réponse, etc., vous pouvez abstraire toute cette logique dans une classe de résultat d'action implémentant IHttpActionResult et l'utiliser dans plusieurs méthodes d'action pour renvoyer la réponse.

Un autre avantage d'utiliser IHttpActionResult comme type de retour est que cela rend la méthode d'action ASP.NET Web API similaire à MVC. Vous pouvez retourner n'importe quel résultat d'action sans être pris dans les formateurs de média.

Bien sûr, comme Darrel l'a noté, vous pouvez chaîner des résultats d'action et créer un puissant micro-pipeline similaire aux gestionnaires de messages eux-mêmes dans le pipeline API. Vous en aurez besoin en fonction de la complexité de votre méthode d'action.

En résumé - ce n'est pas IHttpActionResult contre HttpResponseMessage. Fondamentalement, c'est la manière dont vous voulez créer la réponse. Le faire vous-même ou via une usine.

0 votes

Le problème que j'avais avec la justification de l'usine est que je peux facilement créer des méthodes statiques comme ResponseFactory.CreateOkResponse() qui retournent HttpResponseMessage, et je n'avais pas à gérer les trucs asynchrones lors de la création de la réponse. Un membre de l'équipe a mentionné le fait que l'asynchrone peut être utile si vous avez besoin de faire des E/S pour générer des valeurs d'en-tête. Pas sûr que cela se produise souvent cependant.

0 votes

Je crois que c'est la même chose que de se demander pourquoi avons-nous besoin du modèle de méthode d'usine. Pourquoi ne pas simplement utiliser des méthodes statiques pour créer des objets. Bien sûr, c'est faisable - chaque création d'objet ne mérite pas nécessairement un modèle d'usine approprié. Mais mon avis est que cela dépend de la manière dont vous voulez modéliser vos classes. Voulez-vous avoir de la logique pour créer différents types de réponses toutes entassées dans une classe sous la forme de plusieurs méthodes statiques ou avez-vous différentes classes basées sur une interface. Encore une fois, il n'y a ni bien ni mal. Tout dépend. Quoi qu'il en soit, mon point est qu'il ne s'agit pas d'un choix par rapport à un autre et personnellement, j'aime mieux la chose de l'usine :)

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