339 votes

Pourquoi devrais-je utiliser IHttpActionResult plutôt que HttpResponseMessage ?

J'ai développé avec WebApi et suis passé à 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. Elle semble principalement fournir un moyen LÉGÈREMENT plus facile de créer un HttpResponseMessage.

Je pourrais argumenter 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 é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 augmenté avec certaines appels que j'ai faits : * Avec un exemple utilisant HttpResponseMessage j'ai reçu la réponse en 9545 ms. * En utilisant IHttpActionResult j'ai obtenu la même réponse en 294 ms.

0 votes

@chrislesage 9545 ms est presque 10 secondes. Même 294 ms est assez lent. Si vous avez quelque chose prenant plus de 100 ms alors quelque chose d'autre est à l'œuvre là-bas. Il y a plus à cette histoire qu'il n'y paraît.

318voto

AaronLS Points 12720

Vous pourriez décider de ne pas utiliser IHttpActionResult parce que votre code existant construit un HttpResponseMessage qui ne correspond pas à l'une des réponses préétablies. Cependant, vous pouvez adapter HttpResponseMessage à IHttpActionResult en utilisant la réponse prédéfinie de ResponseMessage. J'ai mis un certain temps à comprendre cela, donc je voulais le poster en montrant que vous n'avez pas nécessairement à choisir l'un ou l'autre :

public IHttpActionResult SomeAction()
{
   IHttpActionResult response;
   //nous voulons un 303 avec la possibilité de définir l'URL de redirection
   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 à partir de laquelle 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é renommé récemment? P.S. Vous avez également manqué 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. Il n'est donc pas nécessaire d'utiliser le mot-clé new 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 préciser 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 argumenté longuement avec l'équipe qu'il n'y avait pas besoin d'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-à-dire, jusqu'à ce que je vois cet 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'ordre 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 action filters.

Cependant, en créant un IHttpActionResult qui peut être enchaîné explicitement 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 construction de la réponse au niveau des couches basses.

Mais voici d'autres avantages de l'utilisation de IHttpActionResult qui méritent d'être mentionnés :

  • Respect du principe de responsabilité unique : fait en sorte que les méthodes d'action aient la responsabilité de servir les requêtes HTTP et ne les implique 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 à 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 son propre ActionResult en implémentant simplement 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 membres de l'équipe API Web peuvent probablement l'articuler mieux, mais voici mes 2 sous.

Tout d'abord, je pense qu'il ne s'agit pas d'une question de l'un ou de 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 réellement la 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 implementant IHttpActionResult comme une fabrique de HttpResponseMessage. Avec cet état d'esprit, il devient maintenant un objet qui doit être retourné 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 d'autres cas, vous avez besoin d'une fabrique pour le faire. Même chose ici.

Si vous voulez retourner 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 retourner une réponse.

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

Évidemment, comme indiqué par Darrel, 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 de l'API. Vous en aurez besoin en fonction de la complexité de votre méthode d'action.

Pour faire court - 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 fabrique.

0 votes

Le problème que j'ai rencontré avec la justification de l'usine est que je peux facilement créer des méthodes statiques comme ResponseFactory.CreateOkResponse() qui renvoient HttpResponseMessage, et je n'avais pas à traiter 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 devez effectuer des entrées/sorties pour générer des valeurs d'en-tête. 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 conception 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, cela dépend de la façon 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 forme de multiples méthodes statiques ou avoir différentes classes basées sur une interface. Encore une fois, il n'y a pas de bien ou de mal. Tout dépend. Quoi qu'il en soit, mon point est que ce n'est pas l'un ou l'autre et personnellement, je préfère la chose de l'usine mieux :)

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