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 =
Newtonsoft.Json.Formatting.Indented;
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:
- You can create a static list of formatters and setup them and pass it to methods every time you want to call methods.
- You can extend the first solution a bit more and create a new extension method for
HttpContentwhich uses the shared formatters. SoYourGetAsync<T>()will callGetAsync<T>(SharedFormatters). - You have the option of setting up the static formatter collection of
HttpContentExtensionsclass using reflection. Then the setting will be always used by those extension methods.
Example
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
{
get
{
var p = typeof(HttpContentExtensions).
GetProperty("DefaultMediaTypeFormatterCollection",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static);
return (MediaTypeFormatterCollection)p.GetValue(null, null);
}
}
}
Then in startup of your application, you can setup formatters in a single point:
var jsonFormatter = HttpClientDefaults.MediaTypeFormatters
.OfType<JsonMediaTypeFormatter>().FirstOrDefault();
// 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>();
}