ASP.NET Web API Content Negotiation and Accept-Charset

There are several good blogs on content negotiation in ASP.NET Web API (see for example ASP.NET Web API: How content negotiation works?) describing how to get JSON, XML, and other response formats depending on what you ask for in a request using the Accept HTTP request header field.

However, recently we added support for the header Accept-Charset which can be used by the client to indicate which character encoding it prefers the response to be encoded with. Typical encodings are UTF-8 and UTF-16 (and our built-in formatters support those) but the set is extensible to other encodings as well.

Note: This is the first in a series of blogs on upcoming features that have been checked into our CodePlex source code repository but haven’t yet been released as part of our official installer. Think of this as a sneak-peak for you to try out and comment on as part of our source code repository (see Getting Started With ASP.NET Web Stack Source on CodePlex for details).

Seeing Accept-Charset in Action

To see how the Accept-Charset header affects the content negotiation it is simplest to use Fiddler. In the following we use the completely vanilla out-of-the-box ValuesController without any changes – we just run it. In Fiddler we use the Composer tab to send a request to the ValuesController like this:


The response coming from the server looks like this. Note the media type parameter charset=utf-8:


Now, go back to the composer tab and add Accept-Charset: utf-16 and you will see this response:


Note also that the Content-Length is twice as big as UTF-16 takes more space.

Now, you can also use q-values with the Accept-Charset header to indicate multiple values with varying quality factors associated. For example if you in the composer tab insert the header field Accept-Charset: utf-16, utf-8; q=0.5 (which means I prefer UTF-16 but can also take UTF-8) then you get the same response as above with a UTF-16 encoded response.

Changing the Default Encodings

The default encoding used by the built-in formatters is UTF-8. This means that if the request doesn’t indicate any preference then we will use UTF-8. However, you can easily change this on a per-formatter basis by changing the SupportEncodings property on the MediaTypeFormatter class. For example, if you want to swap the default encoding from UTF-8 with UTF-16 then you can just reverse the default list so that UTF-16 is fist and UTF-8 is second (see line 3-5):

    1: protected void Application_Start()
    2: {
    3:     Encoding oldDefault = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedEncodings[0];
    4:     GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedEncodings.Add(oldDefault);
    5:     GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedEncodings.RemoveAt(0);
    7:     AreaRegistration.RegisterAllAreas();
    9:     RegisterGlobalFilters(GlobalFilters.Filters);
   10:     RegisterRoutes(RouteTable.Routes);
   12:     BundleConfig.RegisterBundles(BundleTable.Bundles);
   13: }

When running the same sample above you will see a UTF-16 response when no accept-charset header is present. However, if you set the accept-charset header to UTF-8 then you will still get that.

Have fun!

Henrik Tags:,webapi,rest,http