224

Several months ago, Microsoft decided to change up the HttpResponseMessage class. Before, you could simply pass a data type into the constructor, and then return the message with that data, but not anymore.

Now, you need to use the Content property to set the content of the message. The problem is that it is of type HttpContent, and I can't seem to find a way to convert a string, for example, to HttpContent.

Does anyone know how to deal with this issue? Thanks a lot.

j0k
  • 22,600
  • 28
  • 79
  • 90
praetor
  • 3,195
  • 2
  • 23
  • 21

8 Answers8

267

For a string specifically, the quickest way is to use the StringContent constructor

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

There are a number of additional HttpContent class descendants for other common scenarios.

Jim O'Neil
  • 23,344
  • 7
  • 42
  • 67
147

You should create the response using Request.CreateResponse:

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

You can pass objects not just strings to CreateResponse and it will serialize them based on the request's Accept header. This saves you from manually choosing a formatter.

Kols
  • 3,641
  • 2
  • 34
  • 42
Florin Dumitrescu
  • 8,182
  • 4
  • 33
  • 29
  • It automatically works with the content types so you can do xml/json without extra code –  Apr 13 '16 at 10:08
  • I think it would be more correct to call `CreateErrorResponse()` if the response is an error, as it is in this answer's example. Inside my try-catch I'm using: `this.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "message", exception);` And, this is the correct answer if you're at all concerned about respecting the caller's Accept header, without extra shenanigans.(and you're using WebAPI) – JMD Nov 21 '16 at 23:56
  • 4
    @FlorinDumitrescu His point was that this ONLY works for when you inherit `ApiController`. If you are only inheriting `Controller` instead, it doesn't work, and you have to create it yourself: `HttpResponseMessage msg = new HttpResponseMessage(); msg.Content = new StringContent("hi"); msg.StatusCode = HttpStatusCode.OK;` – vapcguy Mar 26 '18 at 23:32
77

Apparently the new way to do it is detailed here:

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

To quote Henrik,

HttpResponseMessage response = new HttpResponseMessage();

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

So basically, one has to create a ObjectContent type, which apparently can be returned as an HttpContent object.

BurnsBA
  • 4,347
  • 27
  • 39
praetor
  • 3,195
  • 2
  • 23
  • 21
76

The easiest single-line solution is to use

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

For serialized JSON content:

return new HttpResponseMessage( HttpStatusCode.OK ) {Content =  new StringContent( SerializedString, System.Text.Encoding.UTF8, "application/json" ) };
Igor Monteiro
  • 933
  • 1
  • 11
  • 29
Simon Mattes
  • 4,866
  • 2
  • 33
  • 53
  • this didn't work for me because IHttpActionResult requires return type of ResponseMessageResult. See my answer below for what I ended up with. Also note, I did factor in nashawn's JsonContent (as derived from StringContent base class). – Adam Cox Apr 03 '17 at 15:35
  • 2
    Just wrap the HttpResponseMessage then: return new ResponseMessageResult( return new HttpResponseMessage( HttpStatusCode.OK ) { new StringContent( "Your message here" ) } ); **:)** – Simon Mattes Apr 04 '17 at 18:29
42

For any T object you can do:

return Request.CreateResponse<T>(HttpStatusCode.OK, Tobject);
ScubaSteve
  • 7,724
  • 8
  • 52
  • 65
  • 6
    Except `Request` is only available with a `CreateResponse` method if you are inheriting `ApiController`. It will not work if using `Controller`. – vapcguy Mar 26 '18 at 23:35
16

You can create your own specialised content types and then assign them to the HttpResponseMessage.Content property.

For example below one for JSON content and one for XML 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
  • 8,252
  • 4
  • 48
  • 56
7

Inspired by Simon Mattes' answer, I needed to satisfy the IHttpActionResult required return type of ResponseMessageResult. Also using nashawn's JsonContent, I made this :

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

See nashawn's answer for JsonContent.

spaleet
  • 838
  • 2
  • 10
  • 23
Adam Cox
  • 3,341
  • 1
  • 36
  • 46
-2

No doubt that you are correct Florin. I was working on this project, and found that this piece of code:

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

Could be replaced with:

response.Content = new StringContent(string product);
jmeinlschmidt
  • 1,446
  • 2
  • 14
  • 33
  • 3
    This answer does not seem relevant to the question and does not show how to go from an object (Product) to a string – mageos Dec 14 '18 at 21:58