WebAPI not returning XML even with correct Accepts header
I'm using ASP.NET WebAPI RC, and hosting an API controller with nothing fancy about it. Everything works fine with JSON, but I'm testing requesting different formats using the Accepts header, and that's where I'm having trouble.
I'm using jQuery to issue an AJAX request, and setting the 'dataType' parameter of the request. This correctly sets the appropriate Accept header as you will see below.
$.ajax({
type: method,
url: url,
dataType: "xml",
data: data || null,
success: function (data) {
// omitted
}
});
Here is a save of the fiddler request/response. As you can see the Accept header says application/xml, but WebAPI returned JSON. I have also tried manually setting the Accept header to just "application/xml" (so it doesn't have the text/html stuff as well), but to no avail.
What the heck am I missing? (note: I've snipped some confidential info in the data but didn't tweak it otherwise)
GET http://localhost/insp**snip**6716 HTTP/1.1
Host: localhost
Connection: keep-alive
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.60 Safari/537.1
Accept: application/xml, text/xml, */*; q=0.01
Referer: http://localhost/inspector/api/test?
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: m=34e2:|2c69:t|47ba:t|4e99:t; .INSPECTOR3COOKIE=08BA683091E2A457B1832E9B*snip*F911D9ED97076
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
Date: Fri, 03 Aug 2012 22:27:42 GMT
Content-Length: 1816
{"Id":2416716,"ProjectId":36,"Url":"http://ins *snip, but obviously this is JSON not XML *
I'd like to point out I'm not tweaking any formatters in AppStart or anything, so as far as I understand, the JSON and XML formatters should be enabled by default.
UPDATE: I figured it out -- check my own answer below
I figured it out!
I had this in my AppStart, because I wanted the Xml serializer not the DataContract serializer:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
HOWEVER... apparently there is something about my model that makes the Xml Serializer think it can't serialize it. I am guessing that is causing WebAPI to decide to use the JSON formatter instead.
It's completely non-intuitive that this harmless looking setting could actually affect which formatter is used. Hope the WebAPI people see this :)
Some kind of tool that let you understand the inputs and outputs of content negotiation process so you can debug issues like this would be nice.
The current answers in this thread already call out a lot of the reasons but just to summarize, the XmlSerializer only supports a limited number of types.
When looking for the "best" formatter, the DefaultContentNegotiator, as correctly described by AASoft, asks each of the formatters whether they can support a particular type. It then matches those formatters against the accept headers in the request.
If it doesn't find any match based on the accept headers then it picks the first that can serialize the type, in this case the JSON formatter. However, you can configure the DefaultContentNegotiator to instead of returning a default format then return a 406 None Accepted status code. This indicates to the client that no matching representation could be found and instead of sending data that the client may not be able to use it generates an error response.
Setting this option is described in the blog "ASP.NET Web API Updates – May 14" [1] under the section "Content Negotiation Improvements".
Hope this helps,
Henrik
[1] http://blogs.msdn.com/b/henrikn/archive/2012/05/14/asp-net-web-api-updates-may-14.aspx
I had the same issue but fixed it by adding default constructors to all the models that I was returning.
The XML serializer creates blank model objects and then populates it via the setters on the properties. If the setters are protected or private then that property will not get serialized either
链接地址: http://www.djcxy.com/p/20398.html