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
HttpContent
which uses the shared formatters. SoYourGetAsync<T>()
will callGetAsync<T>(SharedFormatters)
. - 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.
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>();
}