339 votes

Pourquoi devrais-je utiliser IHttpActionResult à la place de HttpResponseMessage?

J'ai développé avec WebApi et j'ai ensuite migré vers WebApi2 où Microsoft a introduit une nouvelle interface IHttpActionResult qui semble être recommandée d'être utilisée plutôt que de retourner un HttpResponseMessage. Je suis confus sur les avantages de cette nouvelle interface. Il semble surtout fournir un moyen LÉGÈREMENT plus simple de créer un HttpResponseMessage.

Je soutiendrais que c'est de "l'abstraction pour l'abstraction". Est-ce que je rate quelque chose? Quels sont les avantages concrets que j'obtiens en utilisant cette nouvelle interface, à part peut-être gagner 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 se sont nettement améliorées avec certains appels que j'ai faits : * Avec un exemple utilisant HttpResponseMessage, j'ai reçu la réponse en 9545 ms. * En utilisant le IHttpActionResult, j'ai reçu la même réponse en 294 ms.

0 votes

@chrislesage 9545 ms, c'est presque 10 secondes. Même 294 ms est assez lent. Si quelque chose prend plus de 100 ms, alors il y a autre chose en jeu. 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 à une 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, donc je voulais le poster en montrant que vous n'êtes pas 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;
}

Remarquez que ResponseMessage est une méthode de la classe de base ApiController dont votre contrôleur devrait 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é récemment renommé? P.S. Vous avez également oublié 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 est donc simplement un appel de méthode. Ainsi, 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 rendre plus clair 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 capacité ne disparaîtra pas. J'ai ressenti la même chose que vous et j'ai argumenté longuement avec l'équipe qu'il n'était pas nécessaire d'ajouter une abstraction supplémentaire. Quelques arguments ont été avancés pour justifier son existence mais rien ne m'a convaincu que cela en valait la peine.

C'est, jusqu'à ce que je voie ce exemple de Brad Wilson. Si vous construisez des classes IHttpActionResult de manière à ce qu'elles puissent être enchaînées, 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'ordonnancement de ces ActionFilters n'est pas évident lors de la lecture de la méthode d'action, c'est pourquoi je ne suis pas fan des filtres d'actions.

Cependant, en créant un IHttpActionResult qui peut être explicitement enchaîné 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 le test unitaire 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 quelques autres avantages de l'utilisation de IHttpActionResult qui valent la peine d'être mentionnés :

  • Respect du principe de responsabilité unique : les méthodes d'action ont la responsabilité de traiter les requêtes HTTP et ne les impliquent pas dans la création des messages de réponse HTTP.
  • Implémentations utiles déjà définies dans les résultats System.Web.Http.Results notamment : Ok NotFound Exception Unauthorized BadRequest Conflict Redirect InvalidModelState (lien vers la liste complète)
  • Utilise Async et Await par défaut.
  • Facile de créer son 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 n'est que mon opinion personnelle et les gens de l'équipe API Web peuvent probablement mieux l'articuler mais voici mon avis.

Tout d'abord, je pense qu'il ne s'agit pas d'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 devrez probablement 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 fabrique de HttpResponseMessage. Avec cet état d'esprit, cela devient maintenant un objet qui doit être renvoyé et une fabrique 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 certains cas, vous avez besoin d'une fabrique 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 une réponse.

Un autre avantage d'utiliser IHttpActionResult en tant que type de retour est que cela rend la méthode d'action ASP.NET Web API similaire à MVC. Vous pouvez renvoyer n'importe quel résultat d'action sans vous retrouver piégé dans des formateurs de médias.

Bien sûr, comme l'a souligné Darrel, vous pouvez enchaîner les résultats d'action et créer un puissant micro-pipeline similaire aux gestionnaires de messages eux-mêmes dans le pipeline API. Cela sera nécessaire en fonction de la complexité de votre méthode d'action.

En résumé, ce n'est pas IHttpActionResult versus HttpResponseMessage. Fondamentalement, c'est comment vous voulez créer la réponse. Le faire vous-même ou par le biais d'une fabrique.

0 votes

Le problème que j'ai rencontré avec la justification de l'utilisation de la fabrique est que je peux facilement créer des méthodes statiques comme ResponseFactory.CreateOkResponse() qui renvoient HttpResponseMessage, et je n'ai pas eu à gérer les choses 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 opérations d'E/S pour générer des valeurs d'en-tête. Je ne suis pas sûr que cela se produise souvent cependant.

0 votes

Je pense 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 un modèle de fabrique approprié. Mais à mon avis, cela dépend de la façon dont vous voulez modéliser vos classes. Voulez-vous avoir une logique pour créer différents types de réponses tous entassés dans une classe sous forme de multiples méthodes statiques ou avoir 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 que ce n'est pas l'un par rapport à l'autre et personnellement j'aime mieux la chose de la fabrique :)

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