web-dev-qa-db-fra.com

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 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();
    }
}
302
Jason Roell

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.

287
AaronLS

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.

83
Darrel Miller

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:

  • Respect du principe de responsabilité unique : attribue aux méthodes d'action la responsabilité de répondre aux demandes HTTP et ne les implique pas dans la création des messages de réponse HTTP.
  • Implémentations utiles déjà définies dans System.Web.Http.Results, à savoir: OkNotFoundExceptionUnauthorizedBadRequestConflictRedirectInvalidModelState ( lien vers la liste complète )
  • Utilise async et attend 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 .
59
Behzad Bahmanyar
// this will return HttpResponseMessage as IHttpActionResult
return ResponseMessage(httpResponseMessage); 
32
Adam Tal

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.

17
Badri

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.

5
Peter.Wang

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.

3
appletwo

Nous avons les avantages suivants d’utiliser IHttpActionResult sur HttpResponseMessage:

  1. En utilisant le 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.
  2. Les tests unitaires de la méthode du contrôleur mis en œuvre seront plus faciles.
  3. Utilise async et await par défaut.
1
Debendra Dash