Inf*_*oop 31 asp.net asp.net-web-api
我正在使用ASP.NET WebAPI RC,并托管一个没有任何花哨的API控制器.使用JSON一切正常,但我正在测试使用Accepts标头请求不同的格式,这就是我遇到麻烦的地方.
我正在使用jQuery发出AJAX请求,并设置请求的'dataType'参数.这将正确设置相应的Accept标头,如下所示.
$.ajax({
type: method,
url: url,
dataType: "xml",
data: data || null,
success: function (data) {
// omitted
}
});
Run Code Online (Sandbox Code Playgroud)
这是fiddler请求/响应的保存.正如您所见,Accept标头显示了application/xml,但WebAPI返回了JSON.我也尝试手动将Accept标头设置为"application/xml"(因此它也没有text/html的东西),但无济于事.
我错过了什么?(注意:我已经在数据中剪断了一些机密信息,但没有对其进行调整)
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 *
Run Code Online (Sandbox Code Playgroud)
我想指出我没有调整AppStart中的任何格式化程序或任何东西,所以据我所知,默认情况下应该启用JSON和XML格式化程序.
更新:我想通了 - 检查我自己的答案如下
Inf*_*oop 41
我想到了!
我在AppStart中有这个,因为我想要Xml序列化程序而不是DataContract序列化程序:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
Run Code Online (Sandbox Code Playgroud)
但是......显然我的模型有一些东西让Xml Serializer认为它不能序列化它.我猜这是导致WebAPI决定使用JSON格式化程序.
完全不直观的是,这种无害的外观设置实际上可能会影响使用哪种格式化程序.希望WebAPI的人看到这个:)
某种工具可以让您了解内容协商过程的输入和输出,这样您就可以调试这样的问题.
Kev*_*ady 13
我有同样的问题,但通过向我返回的所有模型添加默认构造函数来修复它.
XML序列化程序创建空白模型对象,然后通过属性上的setter填充它.如果setter受保护或私有,那么该属性也不会被序列化
小智 12
此线程中的当前答案已经提出了很多原因,但总结一下,XmlSerializer只支持有限数量的类型.
在查找"最佳"格式化程序时,正如AASoft正确描述的,DefaultContentNegotiator会询问每个格式化程序是否可以支持特定类型.然后,它将这些格式化程序与请求中的接受标头进行匹配.
如果它没有根据accept标头找到任何匹配,那么它会选择第一个可以序列化类型的匹配项,在本例中是JSON格式化程序.但是,您可以配置DefaultContentNegotiator而不是返回默认格式,然后返回406 None Accepted状态代码.这向客户端指示不能找到匹配的表示,而不是发送客户端可能无法使用的数据,而是生成错误响应.
设置此选项的内容在"内容协商改进"部分的博客"ASP.NET Web API更新 - 5月14日"[1]中进行了描述.
希望这可以帮助,
亨里克
[1] http://blogs.msdn.com/b/henrikn/archive/2012/05/14/asp-net-web-api-updates-may-14.aspx
小智 5
答案已经提供,但我认为我会把我的发现放在一起,这样对以后来的人来说可能会有所帮助.
罪魁祸首是IEnumerable.例如,返回包含IEnumerable的类Album的对象并且永远不会获得XML返回 - 仅JSON.
我用了
GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
Run Code Online (Sandbox Code Playgroud)
在Global.asax中也是如此.这对于xml返回实际上是必需的.我仍然没有得到XML.
然后我将IEnumerable更改为List,它工作正常.看起来Web API中的XML Formatter无法处理返回对象中的IEnumerable.
希望这可以帮助.