Can't set Content-Type header on HttpResponseMessage headers?

84,589

Solution 1

Have a look at the HttpContentHeaders.ContentType Property:

response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");

if (response.Content == null)
{
    response.Content = new StringContent("");
    // The media type for the StringContent created defaults to text/plain.
}

Solution 2

Something is missing in ASP Web API: the EmptyContent type. It will allow sending an empty body while still allowing all content-specific headers.

Put the following class somewhere in your code :

public class EmptyContent : HttpContent
{
    protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        return Task.CompletedTask;
    }
    protected override bool TryComputeLength(out long length)
    {
        length = 0L;
        return true;
    }
}

Then use it as you wish. You now have a content object for your extra headers.

response.Content = new EmptyContent();
response.Content.Headers.LastModified = file.DateUpdatedUtc;

Why use EmptyContent instead of new StringContent(string.Empty)?

  • StringContent is a heavy class that executes lots of codes (because it inherits ByteArrayContent)
    • so let's save a few nanoseconds
  • StringContent will add an extra useless/problematic header: Content-Type: plain/text; charset=...
    • so let's save a few network bytes
Share:
84,589

Related videos on Youtube

Jez
Author by

Jez

Long-time coder, with some interest in French and Philosophy. I sometimes hang out in the English Language & Usage chatroom. Check out my Firefox addons! :-)

Updated on July 13, 2020

Comments

  • Jez
    Jez almost 4 years

    I'm using the ASP.NET WebApi to create a RESTful API. I'm creating a PUT method within one of my controllers, and the code looks like this:

    public HttpResponseMessage Put(int idAssessment, int idCaseStudy, string value) {
        var response = Request.CreateResponse();
        if (!response.Headers.Contains("Content-Type")) {
            response.Headers.Add("Content-Type", "text/plain");
        }
    
        response.StatusCode = HttpStatusCode.OK;
        return response;
    }
    

    When I PUT to that location with the browser via AJAX, it gives me this Exception:

    Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.

    But isn't Content-Type a perfectly valid header for a response? Why am I getting this exception?

  • Jez
    Jez over 11 years
    What if the response has no content (so .Content is null)? I'm wanting to set the Content-Type header even though there's no content, otherwise Firefox complains with a "no element found" error.
  • Feidex
    Feidex over 11 years
    You could also try setting response.StatusCode = HttpStatusCode.NoContent instead of adding the Content-Type header field.
  • Jez
    Jez over 11 years
    Cool, the dummy response.Content = new StringContent(""); worked. I am still left wondering why response.Headers even exists, though.
  • Feidex
    Feidex over 11 years
    For the headers that are not Content-related.
  • Jez
    Jez over 11 years
    Well then it's a misleading Exception message. It's not that Content- stuff doesn't belong in an HTTP response, it's that those headers are treated specially by WebApi.
  • Feidex
    Feidex over 11 years
    Yes; WebApi separates the header fields into response header and content header.
  • Chris Marisic
    Chris Marisic over 8 years
    This is just ridiculous. I'm so glad WebApi is done. Long live MVC.
  • SandRock
    SandRock almost 5 years
    There is a problem with StringContent: some problematic headers are sent: Content-Type and Content-Language.