Default json formatter settings for HttpClient

When using Web API, after getting the response, to convert the response to a typed result, you can use ReadAsAsync<T> method of Content property of the response. Sometimes you need to deserialize the json result based on some special josn formatter serializer settings. The method has a signature which allows allows you to pass a custom list of MediaTypeFormatter. It use formatters which you pass or if you don’t pass any formatter it uses its default formatters.

For example, you can use such code to use a custom formatter settings during deserialization:

var formatters = new MediaTypeFormatterCollection();
var jsonFormatter = formatters.OfType<JsonMediaTypeFormatter>().FirstOrDefault();
//Setup jsonFormatteru using its properties like SerializerSettings

HttpClient client = new HttpClient();
var response = await client.GetAsync("http://localhost:58045/api/products/1");
if (response.IsSuccessStatusCode)
    var result = await response.Content.ReadAsAsync<Product>(formatters);

In a web application you can control this setting from a single point and then the framework will use the same settings for all requests:

HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter.SerializerSettings.Formatting =

But can we have a default formatter setting to be able to control formatter setting from a single point, like what you have in web applications?

GetAsync method is an extension method for HttpContent class. HttpContent extension methods are defined in HttpContentExtensions and they use a private static MediaTypeFormatterCollection containing JsonMediaTypeFormatter, XmlMediaTypeFormatter and new FormUrlEncodedMediaTypeFormatter.

You can use either of the following solutions to have a centralized point of settings for formatters:

  1. You can create a static list of formatters and setup them and pass it to methods every time you want to call methods.
  2. You can extend the first solution a bit more and create a new extension method for HttpContent which uses the shared formatters. So YourGetAsync<T>() will call GetAsync<T>(SharedFormatters).
  3. You have the option of setting up the static formatter collection of HttpContentExtensions class using reflection. Then the setting will be always used by those extension methods.


As an example, I will share some code to implement 3rd solution. You can create a class which expose the static private DefaultMediaTypeFormatterCollection property of HttpContextException:

public class HttpClientDefaults
    public static MediaTypeFormatterCollection MediaTypeFormatters
            var p = typeof(HttpContentExtensions).
                    System.Reflection.BindingFlags.NonPublic | 
            return (MediaTypeFormatterCollection)p.GetValue(null, null);

Then in startup of your application, you can setup formatters in a single point:

var jsonFormatter = HttpClientDefaults.MediaTypeFormatters

// Setup jsonFormatter, for example using jsonFormatter.SerializerSettings

The setting will be used for all extension methods to deserialize from json and you don’t need to change the way that you call those methods:

HttpClient client = new HttpClient();
var response = await client.GetAsync("http://localhost:58045/api/products/1");
if (response.IsSuccessStatusCode)
    var result = await response.Content.ReadAsAsync<Product>();

You May Also Like

About the Author: Reza Aghaei

I’ve been a .NET developer since 2004. During these years, as a developer, technical lead and architect, I’ve helped organizations and development teams in design and development of different kind of applications including LOB applications, Web and Windows application frameworks and RAD tools. As a teacher and mentor, I’ve trained tens of developers in C#, ASP.NET MVC and Windows Forms. As an interviewer I’ve helped organizations to assess and hire tens of qualified developers. I really enjoy learning new things, problem solving, knowledge sharing and helping other developers. I'm usually active in .NET related tags in stackoverflow to answer community questions. I also share technical blog posts in my blog as well as sharing sample codes in GitHub.

Leave a Reply

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