Sometimes (or perhaps, quite often?) you only need to support JSON in your ASP.NET Web API. In these cases, the ability of Web API pipeline to facilitate various media types is of no value for you – and you probably do not care at all about content negotiation.

In such situations it is often suggested to remove other media type formatters and only leave JsonMediaTypeFormatter. In fact, the author of this blog has earned almost 20 StackOverflow points for this type of suggestion.

However, there is even better way to solve this problem, and you’ll love it if you are into micro-optimizations.

JSON in Web API – the formatter based approach

As mentioned in the introduction, the most common approach to support JSON only is to clear other formatters and leave only JsonMediaTypeFormatter around.

Given an instance of HttpConfiguration you’d simply clear all and re-add JsonMediaTypeFormatter:

C#

1

2

configuration.Formatters.Clear();

configuration.Formatters.Add(newJsonMediaTypeFormatter());

However, the caveat here is that even though we cleared all other formatters; the entire content negotiation process is still happening – which is a tiny overhead, you shouldn’t really have to pay for. Because we do know the outcome already, so why waste any cycles at all with conneg?

Enter approach number 2 – customizing content negotiation – which happens to be better suited for this task.

JSON in Web API – the conneg based approach

The better way to achieve this goal is to replace the default Web API’s content negotiation mechanism (or, in short, conneg), with a custom one that doesn’t do anything except yields JSON result straight away.

The extensibility interface for conneg is IContentNegotiator, and it’s Negotiate method. It’s role is to take the Type definition, request and the collection of formatters – all these products will participate in the conneg process.

Based on those “ingredients”, it then returns a ContentNegotiationResult which is a wrapper object around the outcome of the negotiation – the selected headers and the selected formatter.

Following the feedback from Youssef Moussaoui from ASP.NET team, I have changed the original approach a bit. In this specific scenario, we will pass in an instance of JsonMediaTypeFormatter into a customized conneg negotiator to always return the content type of application/json and the predefined formatter – JsonMediaTypeFormatter. This way we avoid re-creating the formatter per every request, and also we allow the user to pass in custom serializer settings.

So now, instead of relying on DefaultContentNegotiator, which does a lot of things in its Negotiateimplementation, we plugged in a custom one that only supports JSON and immediately returns that.

On a side note, you may wish to revisit my post about Content Negotiation to understand better what each of these steps does and how to customize it. Bottom line here is, that with this custom IContentNegotiator you have, in an elegant and performance friendly way got rid of all content negotiation in your application and directed everything towards being JSON based only.

Naturally, if you now run your application, every single request will use only your new IContentNegotiator.

In this approach it seems that serialization settings aren’t honored. Is that expected?

http://www.strathweb.com/ Filip W

yeah expected – that was intended to be a simple example. With that said, there are considerations for not recreating the formatter per request, so I updated the code and now you can provide your own serializer settings

http://www.dotnetjalps.com/ Jalpesh Vadgama

Nice post!!

Agustin Colchado

Very useful post! I was looking into this since I really only need to support JSON and wanted to reduce the overhead.

Any known side affects? Negative or positive ones?

http://dmitry-pavlov.com/ Dmitry Pavlov

Thanks! This way is the most elegant I saw.

Md.Ibrahim

That is genius!

trondhuso

Now, if you want to support both json and xml? I understand I have to add XmlMediaTypeFormatter and JsonMediaTypeFormatter. How do I then check for which on in the constructor?
And what about the Negotiate?

http://www.strathweb.com/ Filip W

then you don’t do anything, since json and xml are supported out of the box

trondhuso

yes, right. Let me rephrase the question. What if I want to have more control on how the XML and/or the Json is generated. Do I still use the out of the box formatters, or do I create my own formatters?

Btw: Very nice posts on formatters and also conneg.

http://www.strathweb.com/ Filip W

out of the box, one is JSON.NET, and the other is DataContractSerializer or XmlSerializer (you can switch to the latter by setting UseXmlSerializer flag on the XML formatter ).