A while ago I wrote a post about formatters in MVC 6.
Since then, there have been some changes regarding XML handling and an interesting feature that was added recently that was not part of that post, so I think it warranties a follow up. XML formatter is now removed by default. On top of that, MVC 6 will attempt to sniff out whether your request is originating from a browser’s address bar and adjust content negotiation accordingly.
JSON only by default π
First of all, the XML formatters (input and output) are now removed by default - this was introduced in this PR.
As a result the only output formatters you’ll find plugged in out of the box are:
- HttpNoContentOutputFormatter - handling 204 responses
- TextPlainFormatter - handling string responses
- JsonOutputFormatter - handling everything else
To use XML formatters, you have to opt into input/output XML formatters on application startup:
services.Configure<MvcOptions>(options =>
{
options.AddXmlDataContractSerializerFormatter();
});
Additionally XML formatters have been moved into a separate package - Microsoft.AspNet.Mvc.Xml, so you will need to add that one to your project.json too.
Requests from the browser π
If you recall working with the Web API framework, since it was capable of producing both XML and JSON responses, the relevant formatter to write the response would be selected using a specific order of precedence. Unless you defined some MediaTypeMappings, Accept header would be the highest authority.
And if you made the request from the browser’s address bar the Accept header might look something like this (this varies by the browser, but the gist is the same):
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,\*/\*;q=0.8
As a result Web API would respond with XML, which was technically OK but typically not inline with what the user wanted, as the majority of people wanted to just see JSON.
RespectBrowserAcceptHeader π
In MVC 6, the MvcOptions object (a short reminder that the framework configuration is controlled via it) recently got a new property RespectBrowserAcceptHeader, set by default to false.
It controls the new out-of-the box behavior, where MVC 6, when selecting a formatter will try to sniff out the */* in the Accept header (meaning that the client declares it can handle any media type), and if it’s there, will bypass any content negotiation and just select the first formatter capable of handling the given return type - which will normally be JSON formatter (unless you reordered formatters or injected some custom ones yourself).
Since out of the box MVC 6 is JSON only it doesn’t have that big of an impact, but as soon as you plug in the XML formatters (or any other ones), you will notice that making a request from the browser’s address bar you still get JSON anyway.
The rationale behind this decision is explained by Yishai from the ASP.NET team:
You can switch off this behavior from the options:
services.Configure<MvcOptions>(options =>
{
options.RespectBrowserAcceptHeader = true;
});
Please note that all the changes discussed in this post were introduced after beta3 (which is the version that shipped with the latest Visual Studio 15 CTP6), so to try them out you need to use nightly MVC6 builds available on Myget, build from source or wait for the next release of Visual Studio 15.