Aug 7, 2015

Understanding Content Negotiation in Web API

We know that there are three pillars of the internet, they are:
  • The resource
  • The URL
  • The representation
The first two are very straight forward but the last one is a little confusing to understand. The representation is very important in the modern web. Why? People are currently not only using Desktop computers to browse the web, they are using various types of devices to consume web applications. And the interesting fact is that the various devices expect data in various formats.

For examle a few want data in normal HTML format and some in normat text format. Others need the JSON format and still others in XML format.

The formal definition of Content Negotiation as “the process of selecting the best representation for a given response when there are multiple representations available”.

Now, the fact should be clear, “Content Negotiation” means the client and server can negotiate. It’s not always possible for the server to return data in the requested format. That’s why it’s called negotiation, not demand. Ha.Ha.. And in this case the service will return data in the default format.

The question is, how does the Web API know what the clinet expects? By checking below the header of the request object.

Content-type: which request to API to represent data in this type.

Accept: The acceptable media types for the response, such as “application/json,” “application/xml,” or a custom media type such as "application/vnd.example+xml".

Accept-Charset: The acceptable character sets, such as UTF-8 or ISO 8859-1.

Accept-Encoding:
The acceptable content encodings, such as gzip.

Accept-Language: The preferred natural language, such as “en-us”.

Those are four headers of the request object for the request to the server to represent data in the requested way if possible.

In this example we will implement a simple Web API application and using Fiddler too we will request the Web API to return data in our preferred format. So, let’s start with an example.

Oh, before proceeding to the example I would like to clear up one more concept. We will provide those header values in this format.

Superset/Subset
For example, if the value is "application/json" then the “application is representing the super set” and “json” is the subset of the “application” super set.

If we specify “application/xml” then again “application” is the superset and “xml” is the subset of the application.

Fine, so let’s proceed to the example.

  1. Request data in JSON format
This is currently the most popular format of data representation. So, so first we will see to return data in JSON format from the Web API.

Here is our HTTP header information with  HttpRequest message

User-Agent: Fiddler

Host: localhost:11129


Now, we are seeing that we did not set Content-Type header to request data in JSON format . But Web API is returning data in JSON format. The reason is “If we do not specify any “Content-Type” then by default Web API will return JSON data. Like the following output.



And obviously we could modify the header set like the following to get data in JSON format.

User-Agent: Fiddler

Content-type: application/json

Host: localhost:11129

Both requests will provide the same output in reality.
  1. Request data in XML format
In this example we will request the Web API to return data in XML format. A few years ago this XML would instead be in JSON format. When the application used SOAP based messages (it’s not that SOAP is obsolete in modern applications, it’s still there but people like to use smarter JSON rather than too much informative and stuffy XML).
Now to get data in XML format we need to set the Content-Type header of HttpRequest. Here is an example header set for the following output.

User-Agent: Fiddler

Content-type: application/xml

Host: localhost:11129


And, as out content-type header indicates we are getting data in XML format. 


 Now, those are the two formats that the Web API can supply by default. If we want various types of representations then we need to implement a media type formatter in the Web API.

Understand Accept Header in HttpRequest
In previous examples we saw how a content-type header works with HttpRequest. In this example we will understand the “Accept” header of HttpRequest.

By checking the “Accept” header , the Web API understands which representation the client is able to accept. For example, if we specify that the client can understand the following representation:

application/xml , application/json, text/javascript

Then the Web API will return data in JSON format, the reason is JSON is the default format of the Web API, althought the client’s first preference is the XML format. We will prove it with a small example. Have a look at the following screen.



 Here we have specified that the accept type is as in the following:

application/xml , application/json, text/javascript

And in the response we are getting data in JSON format although we have specified the following:

Content-Type: application/xml

So, here the Web API is ignoring the Content-type header.

Understand Accept-Language header

In the Accept-Language header we can specify the preferred language that we want to get from the Web API application. The Accept-Language header is as in the following:

Accept-Language: en-IN, en-US

It indicates that my first choice is Indian English but if that is not possible then please give me US English and if that is not possible then please provide the data in the default language.




Content Negotiation in ASP.NET Web API

 

The HTTP specification (RFC 2616) defines content negotiation as “the process of selecting the best representation for a given response when there are multiple representations available.” The primary mechanism for content negotiation in HTTP are these request headers:
  • Accept: Which media types are acceptable for the response, such as “application/json,” “application/xml,” or a custom media type such as "application/vnd.example+xml"
  • Accept-Charset: Which character sets are acceptable, such as UTF-8 or ISO 8859-1.
  • Accept-Encoding: Which content encodings are acceptable, such as gzip.
  • Accept-Language: The preferred natural language, such as “en-us”.
The server can also look at other portions of the HTTP request. For example, if the request contains an X-Requested-With header, indicating an AJAX request, the server might default to JSON if there is no Accept header.
In this article, we’ll look at how Web API uses the Accept and Accept-Charset headers. (At this time, there is no built-in support for Accept-Encoding or Accept-Language.)

Serialization

If a Web API controller returns a resource as CLR type, the pipeline serializes the return value and writes it into the HTTP response body.
For example, consider the following controller action:
public Product GetProduct(int id)
{
    var item = _products.FirstOrDefault(p => p.ID == id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return item; 
}
A client might send this HTTP request:
GET http://localhost.:21069/api/products/1 HTTP/1.1
Host: localhost.:21069
Accept: application/json, text/javascript, */*; q=0.01
In response, the server might send:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 57
Connection: Close

{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}
In this example, the client requested either JSON, Javascript, or “anything” (*/*). The server responsed with a JSON representation of the Product object. Notice that the Content-Type header in the response is set to "application/json".

 The HTTP specification (RFC 2616) defines content negotiation as “the process of selecting the best representation for a given response when there are multiple representations available.” The primary mechanism for content negotiation in HTTP are these request headers:

    Accept: Which media types are acceptable for the response, such as “application/json,” “application/xml,” or a custom media type such as "application/vnd.example+xml"
    Accept-Charset: Which character sets are acceptable, such as UTF-8 or ISO 8859-1.
    Accept-Encoding: Which content encodings are acceptable, such as gzip.
    Accept-Language: The preferred natural language, such as “en-us”.

The server can also look at other portions of the HTTP request. For example, if the request contains an X-Requested-With header, indicating an AJAX request, the server might default to JSON if there is no Accept header.

In this article, we’ll look at how Web API uses the Accept and Accept-Charset headers. (At this time, there is no built-in support for Accept-Encoding or Accept-Language.)
Serialization

If a Web API controller returns a resource as CLR type, the pipeline serializes the return value and writes it into the HTTP response body.

For example, consider the following controller action:

public Product GetProduct(int id)
{
    var item = _products.FirstOrDefault(p => p.ID == id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return item;
}

A client might send this HTTP request:

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

In response, the server might send:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 57
Connection: Close

{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}

In this example, the client requested either JSON, Javascript, or “anything” (*/*). The server responsed with a JSON representation of the Product object. Notice that the Content-Type header in the response is set to "application/json".

 

No comments:

Post a Comment