Mettre le contenu dans l'objet HttpResponseMessage?


180

Il y a plusieurs mois, Microsoft a décidé de changer la classe HttpResponseMessage. Avant, vous pouviez simplement passer un type de données dans le constructeur, puis renvoyer le message avec ces données, mais plus maintenant.

Maintenant, vous devez utiliser la propriété Content pour définir le contenu du message. Le problème est qu'il est de type HttpContent, et je n'arrive pas à trouver un moyen de convertir une chaîne, par exemple, en HttpContent.

Quelqu'un sait-il comment traiter ce problème? Merci beaucoup.

Réponses:


216

Pour une chaîne en particulier, le moyen le plus rapide est d'utiliser le constructeur StringContent

response.Content = new StringContent("Your response text");

Il existe un certain nombre de descendants de classe HttpContent supplémentaires pour d'autres scénarios courants.


Voir mon article ci-dessous pour créer vos propres types dérivés de StringContent (par exemple JSON, XML, etc.).
bytedev

135

Vous devez créer la réponse à l'aide de Request.CreateResponse :

HttpResponseMessage response =  Request.CreateResponse(HttpStatusCode.BadRequest, "Error message");

Vous pouvez transmettre des objets non seulement des chaînes à CreateResponse et il les sérialisera en fonction de l'en-tête Accept de la demande. Cela vous évite de choisir manuellement un formateur.


Il fonctionne automatiquement avec les types de contenu afin que vous puissiez faire xml / json sans code supplémentaire

Je pense qu'il serait plus correct d'appeler CreateErrorResponse()si la réponse est une erreur, comme c'est le cas dans l'exemple de cette réponse. Dans mon try-catch que j'utilise: this.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "message", exception); Et c'est la bonne réponse si vous êtes préoccupé par le respect de l'en-tête Accept de l'appelant, sans manigances supplémentaires. (Et vous utilisez WebAPI)
JMD

2
@FlorinDumitrescu Son point était que cela fonctionne UNIQUEMENT lorsque vous héritez ApiController. Si vous n'héritez qu'à la Controllerplace, cela ne fonctionne pas et vous devez le créer vous-même: HttpResponseMessage msg = new HttpResponseMessage(); msg.Content = new StringContent("hi"); msg.StatusCode = HttpStatusCode.OK;
vapcguy

64

Apparemment, la nouvelle façon de le faire est détaillée ici:

http://aspnetwebstack.codeplex.com/discussions/350492

Pour citer Henrik,

HttpResponseMessage response = new HttpResponseMessage();

response.Content = new ObjectContent<T>(T, myFormatter, "application/some-format");

Donc, fondamentalement, il faut créer un type ObjectContent, qui peut apparemment être retourné en tant qu'objet HttpContent.


31
qu'est-ce que myFormatter
Greg

1
@ user1760329 ce serait un new JsonMediaTypeFormatter();ou similaire en fonction de votre format
John

1
ObjectContentn'est pas trouvé, utilisant WCF
Medet Tleukabiluly

2
Je ne qualifierais pas cela de "nouvelle façon de le faire" - cet article que vous référencez le répertorie comme une alternative dans le cas où vous voudriez avoir "un contrôle complet du formateur [de type de média] que vous souhaitez utiliser"
Berne

Merci @praetor. Cela a été vraiment utile pour moi
Utilisateur SO

53

La solution simple ligne la plus simple est d'utiliser

return new HttpResponseMessage( HttpStatusCode.OK ) {Content =  new StringContent( "Your message here" ) };

Pour le contenu JSON sérialisé:

return new HttpResponseMessage( HttpStatusCode.OK ) {Content =  new StringContent( SerializedString, System.Text.Encoding.UTF8, "application/json" ) };

cela n'a pas fonctionné pour moi car IHttpActionResult nécessite le type de retour ResponseMessageResult. Voir ma réponse ci-dessous pour ce que j'ai fini avec. Notez également que j'ai pris en compte le JsonContent de nashawn (dérivé de la classe de base StringContent).
Adam Cox

1
Enveloppez simplement le HttpResponseMessage puis: return new ResponseMessageResult (return new HttpResponseMessage (HttpStatusCode.OK) {new StringContent ("Your message here")}); :)
Simon Mattes

41

Pour tout objet T, vous pouvez faire:

return Request.CreateResponse<T>(HttpStatusCode.OK, Tobject);

5
Sauf Requestn'est disponible qu'avec une CreateResponseméthode si vous héritez ApiController. Cela ne fonctionnera pas si vous utilisez Controller.
vapcguy

15

Vous pouvez créer vos propres types de contenu spécialisés. Par exemple, un pour le contenu Json et un pour le contenu Xml (puis attribuez-les simplement à HttpResponseMessage.Content):

public class JsonContent : StringContent
{
    public JsonContent(string content)
        : this(content, Encoding.UTF8)
    {
    }

    public JsonContent(string content, Encoding encoding)
        : base(content, encoding, "application/json")
    {
    }
}

public class XmlContent : StringContent
{
    public XmlContent(string content) 
        : this(content, Encoding.UTF8)
    {
    }

    public XmlContent(string content, Encoding encoding)
        : base(content, encoding, "application/xml")
    {
    }
}

mise en œuvre très soignée et propre.
Sam

3

Inspiré par la réponse de Simon Mattes, je devais satisfaire le type de retour requis par IHttpActionResult ResponseMessageResult. En utilisant également JsonContent de nashawn, j'ai fini avec ...

        return new System.Web.Http.Results.ResponseMessageResult(
            new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.OK)
            {
                Content = new JsonContent(JsonConvert.SerializeObject(contact, Formatting.Indented))
            });

Voir la réponse de nashawn pour JsonContent.


l'interpolation de cordes semble inutile
Igor Pashchuk

0

Nul doute que vous avez raison Florin. Je travaillais sur ce projet et j'ai trouvé que ce morceau de code:

product = await response.Content.ReadAsAsync<Product>();

Peut être remplacé par:

response.Content = new StringContent(string product);

1
Cette réponse ne semble pas pertinente pour la question et ne montre pas comment passer d'un objet (Produit) à une chaîne
mageos
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.