Content Negotiation & WebAPI

Avishek Patra
3 min readDec 26, 2017

It’s been a bit long, since after my last post… Yeah, I was a bit occupied with a lot of personal unorganized things. So let’s learn about Content Negotiation. It’s an often question pop’s up what is Content Negotiation and how it works. We will go through today with a step-by-step process.

First, begin with the word Negotiation, we often use this word in our daily life, while materializing a deal or making a payment we often negotiate with the other parties to make the deal more win-win situation. In API world the things are same but the negotiation is done based on the content type which will be coming to the client as a response. Which means client and server both will negotiate on the content type to get the best outcome.

Content Negotiation is not related to Web API or .NET framework, but it’s part of the architecture of HTTP client-server communication protocol. That mean’s when client is requested for some information from server then it creates the Request data or payload to the server, which consists of the following information

  1. URL
  2. HTTP Method
  3. Payload (Either passed through body or by query string or may not have a payload at all)
  4. Header Parameters
  5. ContentType (This needs when you’re sending some data to server from client)

Header parameters consists of the following information

GET http://localhost:8080/api/catalogue/1 HTTP/1.1
Host: localhost.:8080
Accept:application/json, text/javascript, */*; q=0.01

So here you’re negotiating with the server to send the response content in JSON, Javascript or anything (*/*) format. Now server based on its supported media types it will respond back. Consider our controller code in API is like the below snippet.

public Catalogue GetCatalogue(int id)
{
var catalogue= _catalogue.FirstOrDefault(c => c.ID == id);
if (catalogue== null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return catalogue;
}

Here we are throwing a HttResponseException in case of null otherwise a CLR object which is the catalogue in this case, so technically action doesn’t know that what will be the response format. So how can our clients get the expected response? Here comes the IContentNegotiator in the picture.

The following steps will be performed during the Content Negotiation

  1. The request pipeline gets the IContentNegotiator service from the HttpConfiguration object. Also, it gets the list of media formats from the HttpConfiguration.Formatters collection, which basically lists out the supported media formats.
  2. After that, it calls IContentNegotiator.Negotiate method, which takes following information as input:
  3. The type of the object to be serialized — So in our case it will be “Catalogue” object
  4. The collection media formatter — HttpConfiguration.Formatters
  5. HTTP Request — The current Http Request Object.

The Negotiate method returns the following information

  1. Which formatter to use — The used formatter.
  2. The media type for the response — The media type or mime type

If No formatter is found Negotiate method returns null and so we can send a 406 NotAcceptable response from our controller.

The following code snippet illustrates how a controller can invoke content negotiation from the action:

public HttpResponseMessage GetCatalogue(int id)
{
var catalogue= new Catalogue(){ Id = id, Name = "Fiction Books" };
IContentNegotiator contentNegotiator = Configuration.Services.GetContentNegotiator();
ContentNegotiationResult result = contentNegotiator.Negotiate(
typeof(Catalogue), Request, Configuration.Formatters);
if (result == null)
{
var response = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
throw new HttpResponseException(response));
}
return new HttpResponseMessage()
{
Content = new ObjectContent(
catalogue,
result.Formatter,
result.MediaType.MediaType
)
};
}

The DefaultContentNegotatior class provides the default implementation of IContentNegotiator, however, we can implement the interface and extend that accordingly.

Originally published at http://coderera.wordpress.com on December 26, 2017.

--

--