HttpClient: How to remove charset from Content-Type header

I was writing client library for one online service and faced situation where I had to remove charset definition from Content-Type header. It was like content type is application/json or response is 415 “Unsupported media type”. I was using HttpClient class to communicate with service and without additional efforts charset doesn’t go away. Here is how I got charset definition away from Content-Type header.

Problem

My problematic code was similar to one shown here.

var newUser = new { Id = 100, Name = "John Doe" };
var newUserJson = JsonConvert.SerializeObject(newUser);
var uri = new Uri("<address to some service>");

using (var client = new HttpClient())
using (var content = new StringContent(newUserJson, Encoding.UTF8, "application/json"))
{
    var result = await client.PostAsync(uri, content);

    // do something with result
}

Replacing in StringContent constructor Encoding.UTF8 with null doesn’t change the situation. In my case I got the following result when running my code.

HttpClient request with charset in content-type header

Charset definition in request content type is the show stopper. To make things more interesting I bring out here all public constructors of StringContent class.

public StringContent(string content);
public StringContent(string content, Encoding encoding);
public StringContent(string content, Encoding encoding, string mediaType);

We either don’t specify content type and get text/plain as default or we specify content type with text encoding. There’s no way to specify just content type.

Why charset with content type?

I guess it comes down to SEO on performance strategies. There are online services like PageSpeed Insights and YSlow that suggest to give charset with textual content type so server on the other end doesn’t have to spend time on guessing correct charset. There’s one benefit more – if server knows charset before content starts then it doesn’t have to recode content that it parsed before charset HTML header.

Removing charset from content-type header

Solution is simple – we can create StringContent with whatever encoding and then set charset to empty string.

using (var client = new HttpClient())
using (var content = new StringContent(newUserJson, Encoding.UTF8, "application/json"))
{
    content.Headers.ContentType.CharSet = "";

    var result = await client.PostAsync(uri, content);

    // do something with result
}

This removes charset definiton from request content type header. My code started work after this change.

Subclassing StringContent

Although my code worked I wasn’t happy with solution like this as I have to remember to set charset to empty string in every method I use HttpClient. I created new StringContentWithoutCharset class that extends StringContent.

public class StringContentWithoutCharset : StringContent
{
    public StringContentWithoutCharset(string content) : base(content)
    {
    }

    public StringContentWithoutCharset(string content, Encoding encoding) : base(content, encoding)
    {
        Headers.ContentType.CharSet = "";
    }

    public StringContentWithoutCharset(string content, Encoding encoding, string mediaType) : base(content, encoding, mediaType)
    {
        Headers.ContentType.CharSet = "";
    }

    public StringContentWithoutCharset(string content, string mediaType) : base(content, Encoding.UTF8, mediaType)
    {
        Headers.ContentType.CharSet = "";
    }
}

This class adds additional constructor that accepts string content and content type. It calls base constructor with UTF8 charset but removes content type charset immediately. This is how my code looks like when using StringContentWithoutCharset class,

var newUser = new { Id = 100, Name = "John Doe" };
var newUserJson = JsonConvert.SerializeObject(newUser);
var uri = new Uri("<address to some service>");

using (var client = new HttpClient())
using (var content = new StringContentWithoutCharset(newUserJson, "application/json"))
{
    var result = await client.PostAsync(uri, content);

    // do something with result
}

This is the solution I am currently using,

Wrapping up

Although I don’t like to extend .NET Framework classes to add just one missing controller I didn’t had much chance this time. Still I’m okay with this solution as it hides the implementation of content-type charset removing from client code using the class. I hope the constructor I created makes its way to .NET Framework and .NET Core one day.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    2 thoughts on “HttpClient: How to remove charset from Content-Type header

    • May 24, 2019 at 11:34 am
      Permalink

      You could also achieve the same result by adding a DelegatingHandler to the HttpClient.
      Then you could use any HttpContent, and it would be applied to all requests made using that client.

      class ClearCharSetHandler : DelegatingHandler
      {
      protected override Task SendAsync(HttpRequestMessage request, CancellationToken token)
      {
      request.Content.Headers.ContentType.CharSet = “”;
      return base.SendAsync(request, token);
      }
      }

    • June 8, 2019 at 1:33 am
      Permalink

      Sheesh, took forever for me to figure this out. Thanks.

    Leave a Reply

    Your email address will not be published. Required fields are marked *