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.

pretor
fonte

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.

Jim O'Neil
fonte
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.

Florin Dumitrescu
fonte
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.

pretor
fonte
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" ) };
Simon Mattes
fonte
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);
ScubaSteve
fonte
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")
    {
    }
}
bytedev
fonte
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.

Adam Cox
fonte
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);
Steven WH
fonte
1
Esta resposta não parece relevante para a pergunta e não mostra como ir de um objeto (Produto) para uma string
mageos