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.

Liked this post? Empower your friends by sharing it!

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.

    3 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.

    • November 5, 2019 at 10:53 pm
      Permalink

      Good afternoon, I have a similar problem, I have exposed a service developed in .net to be consumed from a JAVA application, for some reason I do not know the owner of the application that makes the consumption is demanding that we remove the ContentType from the answer, but if I eliminate it when making the consumption it does not enter the method, everywhere they indicate that the adjustment must be made by the owner of the application that consumes the web services, but they indicated that they will not do it. I appreciate your comments on how to make this adjustment?

      My code for consumption is:

      Public Class FormatoRequerimiento
      Inherits System.Web.UI.Page

      Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

      End Sub

      Public Shared Sub RequerimientoCapital()
      Dim formato As New FormatoRequerimientoCapitalTO
      formato = obtenerObjetoReqCapital()
      HttpContext.Current.Response.Write(FormatoRequerimiento.getJSON(formato))

      End Sub

      Public Shared Function getJSON(ByVal formato As Object) As String
      Return JsonConvert.SerializeObject(New With {.FormatoRequerimientoCapital = formato}, Newtonsoft.Json.Formatting.Indented)
      End Function

      Private Shared Function obtenerObjetoReqCapital() As FormatoRequerimientoCapitalTO
      Dim formato As New FormatoRequerimientoCapitalTO
      Dim resultado As New clsResultadosTO
      Dim obUnidadCaptura As New UnidadCapturaTO
      ———————–

    Leave a Reply

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