¿Poner contenido en el objeto HttpResponseMessage?

180

Hace varios meses, Microsoft decidió cambiar la clase HttpResponseMessage. Antes, simplemente podía pasar un tipo de datos al constructor y luego devolver el mensaje con esos datos, pero ya no.

Ahora, debe usar la propiedad Contenido para establecer el contenido del mensaje. El problema es que es del tipo HttpContent, y parece que no puedo encontrar una manera de convertir una cadena, por ejemplo, a HttpContent.

¿Alguien sabe cómo lidiar con este problema? Muchas gracias.

pretor
fuente

Respuestas:

216

Para una cadena específicamente, la forma más rápida es usar el constructor StringContent

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

Hay varios descendientes adicionales de la clase HttpContent para otros escenarios comunes.

Jim O'Neil
fuente
Vea mi publicación a continuación para crear sus propios tipos derivados de StringContent (por ejemplo, JSON, XML, etc.).
bytedev
135

Debe crear la respuesta usando Request.CreateResponse :

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

Puede pasar objetos no solo cadenas a CreateResponse y los serializará en función del encabezado Aceptar de la solicitud. Esto le ahorra elegir manualmente un formateador.

Florin Dumitrescu
fuente
Funciona automáticamente con los tipos de contenido para que pueda hacer xml / json sin código adicional
Creo que sería más correcto llamar CreateErrorResponse()si la respuesta es un error, como lo es en el ejemplo de esta respuesta. Dentro de mi try-catch estoy usando: this.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "message", exception); Y esta es la respuesta correcta si le preocupa respetar el encabezado Aceptar de la persona que llama, sin travesuras adicionales (y está usando WebAPI)
JMD
2
@FlorinDumitrescu Su punto era que esto SOLO funciona para cuando heredas ApiController. Si solo estás heredando Controller, no funciona, y tienes que crearlo tú mismo: HttpResponseMessage msg = new HttpResponseMessage(); msg.Content = new StringContent("hi"); msg.StatusCode = HttpStatusCode.OK;
vapcguy
64

Aparentemente, la nueva forma de hacerlo se detalla aquí:

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

Para citar a Henrik,

HttpResponseMessage response = new HttpResponseMessage();

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

Básicamente, uno tiene que crear un tipo ObjectContent, que aparentemente puede devolverse como un objeto HttpContent.

pretor
fuente
31
¿Qué es myFormatter
Greg Z.
1
@ user1760329 sería una new JsonMediaTypeFormatter();o similar dependiendo de su formato
John
1
ObjectContentno se encuentra, usando WCF
Medet Tleukabiluly
2
No calificaría esto como la "nueva forma de hacerlo": el artículo al que hace referencia lo enumera como una alternativa en caso de que desee tener "control completo del formateador [tipo de medio] que desea usar"
Bern
Gracias @praetor. Esto ha sido realmente útil para mí
usuario SO
53

La solución más sencilla de una sola línea es usar

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

Para contenido JSON serializado:

return new HttpResponseMessage( HttpStatusCode.OK ) {Content =  new StringContent( SerializedString, System.Text.Encoding.UTF8, "application/json" ) };
Simon Mattes
fuente
esto no funcionó para mí porque IHttpActionResult requiere el tipo de retorno de ResponseMessageResult. Vea mi respuesta a continuación para ver con qué terminé. También tenga en cuenta que factoré en JsonContent de nashawn (derivado de la clase base StringContent).
Adam Cox
1
Simplemente envuelva el HttpResponseMessage y luego: devuelva el nuevo ResponseMessageResult (devuelva el nuevo HttpResponseMessage (HttpStatusCode.OK) {new StringContent ("Su mensaje aquí")}); :)
Simon Mattes
41

Para cualquier objeto T que pueda hacer:

return Request.CreateResponse<T>(HttpStatusCode.OK, Tobject);
ScubaSteve
fuente
55
Excepto Requestsolo está disponible con un CreateResponsemétodo si está heredando ApiController. No funcionará si se usa Controller.
vapcguy
15

Puede crear sus propios tipos de contenido especializado. Por ejemplo, uno para contenido Json y otro para contenido Xml (luego simplemente asignarlos al 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")
    {
    }
}
bytedev
fuente
Implementación muy ordenada y limpia.
Sam
3

Inspirado por la respuesta de Simon Mattes, necesitaba satisfacer el tipo de retorno requerido de IHttpActionResult de ResponseMessageResult. También usando JsonContent de nashawn, terminé con ...

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

Ver la respuesta de nashawn para JsonContent.

Adam Cox
fuente
la interpolación de cuerdas parece innecesaria
Igor Pashchuk
0

No hay duda de que tienes razón Florin. Estaba trabajando en este proyecto y descubrí que este código:

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

Podría ser reemplazado por:

response.Content = new StringContent(string product);
Steven WH
fuente
1
Esta respuesta no parece relevante para la pregunta y no muestra cómo pasar de un objeto (Producto) a una cadena
mageos