Colocar conteúdo no objeto HttpResponseMessage?


180

Há alguns meses, a Microsoft decidiu alterar a classe HttpResponseMessage. Antes, você poderia simplesmente passar um tipo de dados para o construtor e retornar a mensagem com esses dados, mas não mais.

Agora, você precisa usar a propriedade Content para definir o conteúdo da mensagem. O problema é que ele é do tipo HttpContent, e parece que não consigo encontrar uma maneira de converter uma string, por exemplo, para HttpContent.

Alguém sabe como lidar com esse problema? Muito obrigado.

Respostas:


216

Para uma string especificamente, a maneira mais rápida é usar o construtor StringContent

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

Há vários descendentes adicionais da classe HttpContent para outros cenários comuns.


Veja meu post abaixo para criar seus próprios tipos derivados de StringContent (por exemplo, JSON, XML etc.).
bytedev

135

Você deve criar a resposta usando Request.CreateResponse :

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

Você pode passar objetos e não apenas cadeias de caracteres para CreateResponse e eles serão serializados com base no cabeçalho Accept da solicitação. Isso evita que você escolha manualmente um formatador.


Ele automaticamente funciona com os tipos de conteúdo que você possa fazer xml / json sem código extra

Eu acho que seria mais correto chamar CreateErrorResponse()se a resposta for um erro, como no exemplo desta resposta. Dentro do try-catch, estou usando: this.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "message", exception); E, esta é a resposta correta se você estiver preocupado em respeitar o cabeçalho Accept do chamador, sem travessuras extras. (E você está usando o WebAPI)
JMD

2
@FlorinDumitrescu O argumento dele era que isso SOMENTE funciona para quando você herdar ApiController. Se você só estão herdando Controllerem vez disso, ele não funciona, e você tem que criá-lo: HttpResponseMessage msg = new HttpResponseMessage(); msg.Content = new StringContent("hi"); msg.StatusCode = HttpStatusCode.OK;
vapcguy

64

Aparentemente, a nova maneira de fazer isso é detalhada aqui:

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

Para citar Henrik,

HttpResponseMessage response = new HttpResponseMessage();

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

Então, basicamente, é necessário criar um tipo ObjectContent, que aparentemente pode ser retornado como um objeto HttpContent.


31
o que é myFormatter
Greg Z.

1
@ user1760329 seria um new JsonMediaTypeFormatter();ou similar dependendo do seu formato
John

1
ObjectContentnão foi encontrado, usando o WCF
Medet Tleukabiluly

2
Eu não qualificaria isso como a "nova maneira de fazê-lo" - esse artigo que você faz referência o lista como uma alternativa no caso de você querer ter "controle completo do formatador [do tipo de mídia] que deseja usar"
Berna

Obrigado @praetor. Isso foi realmente útil para mim
SO User

53

A solução de linha única mais fácil é usar

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

Para conteúdo JSON serializado:

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

isso não funcionou para mim porque IHttpActionResult requer o tipo de retorno ResponseMessageResult. Veja minha resposta abaixo para o que eu acabei. Observe também que eu levei em consideração o JsonContent do nashawn (como derivado da classe base StringContent).
Adam Cox

1
Apenas envolva o HttpResponseMessage e retorne o novo ResponseMessageResult (retorne o novo HttpResponseMessage (HttpStatusCode.OK) {new StringContent ("Your message here")}); :)
Simon Mattes

41

Para qualquer objeto T, você pode fazer:

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

5
Exceto Requestestá disponível apenas com um CreateResponsemétodo se você estiver herdando ApiController. Não funcionará se estiver usando Controller.
vapcguy

15

Você pode criar seus próprios tipos de conteúdo especializados. Por exemplo, um para o conteúdo Json e outro para o conteúdo Xml (basta atribuí-los ao 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")
    {
    }
}

implementação muito arrumada e limpa.
26416 Sam

3

Inspirado na resposta de Simon Mattes, eu precisava satisfazer o tipo de retorno exigido IHttpActionResult de ResponseMessageResult. Também usando JsonContent da nashawn, acabei com ...

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

Veja a resposta de nashawn para JsonContent.


string de interpolação parece desnecessário
Igor Pashchuk

0

Sem dúvida, você está correto Florin. Eu estava trabalhando nesse projeto e descobri que esse trecho de código:

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

Pode ser substituído por:

response.Content = new StringContent(string product);

1
Esta resposta não parece relevante para a pergunta e não mostra como ir de um objeto (Produto) para uma string
mageos
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.