7. Up until now, we have seen how the Accept and Request Content-Type headers play a role in Conneg algorithm’s decision making process. There is one more way by which Conneg algorithm decides about the Response’s media type and formatter. It is called MediaTypeMapping. Every MediaTypeFormatter has a collection of these mappings in it.
MediaTypeMapping provides a way for the user to add some custom logic and decide whether they would want the formatter to take part in writing the Response. This is different from the default way of just matching media type values(like “application/xml”) present on the Accept and Request Content-Type headers and making decisions.
MediaTypeMapping provides a greater control.
Here I am creating a media type mapping which checks if the Request has a “Browser” header called “Internet Explorer”. If it finds the header, then it would inform the Conneg algorithm that it’s a full match and that the media type formatter having this media type mapping is ready to write the response.
As I mentioned earlier, each MediaTypeFormatter object has a collection of media type mappings available through the MediaTypeMappings property. So, we can add our BrowserMediaTypeMapping object in that collection like below:
NOTE: In the above code snippet, I am just adding the mapping to the existing default formatter collection which has the formatters (in this order): JsonMediaTypeFormatter, XmlMediaTypeFormatter & FormUrlEncodedMediaTypeFormatter.
Now let’s see an example of how the Conneg algorithm behaves when a Request has the “Browser” header:
GET http://kirandev10:9090/MappingTests/GetString HTTP/1.1
HTTP/1.1 200 OK
Date: Sun, 26 Feb 2012 23:58:43 GMT
<?xml version="1.0" encoding="utf-8"?><string>Hello</string>
In the above scenario, a GET request is sent without any Accept header. Usually if this kind of request is sent, Conneg algorithm would pick the 1st formatter in the list of formatters and that would be the JsonMediaTypeFormatter.
But, since the request has a “Browser” header with the value “Internet Explorer”, the XmlMediaTypeFormatter’s BrowserMediaTypeMapping checks this and responds to the Conneg algorithm by giving it a full match.
Hence we are seeing the Response in a “application/xml” format instead of the default “application/json” format.
As you can imagine, MediaTypeMapping provides full power to you to inspect incoming request and make a decision of whether to participate in a response or not.
By default, ASP.NET MVC4 Beta Web API ships with 4 built-in media type mappings. They are:
I will discuss more about these individually in my later posts.
What happens when multiple formatters match an incoming request’s criteria? Which one does the Conneg algorithm choose?
During the Conneg algorithm run, based on bunch of criteria like the Request Accept header, Content-Type header, MediaTypeMapping etc, there is always a possibility that more than one formatter could indicate its availability in writing the Response. As you can imagine, the Conneg algorithm has to choose only one formatter in the end.
The Default Conneg algorithm has the following precedence order to select the final formatter:
1. Formatter match based on Media Type Mapping.
2. Formatter match based on Request Accept header's media type.
3. Formatter match based on Request Content-Type header's media type.
4. Formatter match based on if it can serialize the response data’s Type.
In spite of all this, as mentioned in “Point 6.”, if a user decides to always send a Response in a particular media type, Conneg algorithm will honor it and will not override it.