-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider only adding the JSON formatter by default #1
Comments
对于匿名对象或者array , xml 和json的序列化方式存在较大差异Just for some clarification on the issue: JSON is currently the default. If you create a request without any "Accept" headers, web api seems to return json (probably because it is registered first?) The issue is that all major browsers except IE request specifically for "application/xml" by default if you do a request from the url bar. Asp.net has content negotiation, so it will try to honor the request and selects the Xml formatter (because it is registered). So, ASP.NET is technically doing the right thing. The discussion is just if these lines should be there by default (and the InputFormatter counterpart). Now, I also have some serious opinions on whether content negotiation between xml and json by default is a good idea. Simple examples will always work, but in practice it is ridiculously easy to make things break with valid code. Consider this code: public object Get()
{
return new
{
count = 3,
records = new[] { 1, 2, 3 }
};
} This is a very common pattern for a web api + javascript, and the xml serializer will just blow up here complaining there is no DataContractAttribute in the anonymous object, while Json just works. There are also differences in how both serializers handle things that cause different behavior in applications using json vs xml. Look at this, using a empty web project with latest web api, default settings: public class SomeClass
{
public SomeClass()
{
A = new List<int> { 1, 2 };
B = new List<int> { 1, 2 };
}
public List<int> A { get; set; }
public List<int> B { get; private set; }
}
public class ValuesController : ApiController
{
public SomeClass Get()
{
return new SomeClass();
}
public SomeClass Post([FromBody] SomeClass x)
{
return x;
}
} Now, just get the values with different headers:
{ "A": [1, 2], "B": [1, 2] } Same request with XML:
<SomeClass>
<A>
<d2p1:int>1</d2p1:int>
<d2p1:int>2</d2p1:int>
</A>
</SomeClass> The default xml serializer ignores read only properties, so there is no "B" there, causing different client behavior. Now for some issues in the input serialization: POST /api/values
Accept: application/json
Content-type: application/json
{ "A": [3, 4] } Response: { "A": [1, 2, 3, 4], "B": [1, 2] } And with XML:
<SomeClass>
<A>
<d2p1:int>3</d2p1:int>
<d2p1:int>4</d2p1:int>
</A>
</SomeClass> Here, JSON.NET by default merges lists while the xml serializer replaces it. Those are just some things I found very quickly in real world apps. Some of these settings could even be tuned by default to have similar results (causing a lot of breaking changes), but is it worth the hassle? By having both serializers by default we guarantee there is a huge number of ASP.NET websites out there that have never been properly tested and have broken APIs, as a poor showcase for the platform. I believe that having content negotiation in an application is not that trivial, and is just as internationalization: to make it work, you need to develop and test your application for that. The simple solution is just have a single protocol (json) by default and if you need two formats, you enable it and deal with the consequences just like supporting two languages. Originally posted by @nvivo in aspnet/Mvc#1765 (comment) |
As far as I can tell, IE, by default, uses an "Accept" heading with both "Application/xhtml+xml" and "
*/*
" with no priority setting, which WebAPI apparently takes as "JSON is as good as anything else, give him JSON".Chrome, OTOH, uses an Accept of "
text/html, application/xhtml+xml, application/xml; q=0.9, image/webp, */*; q=0.8
" which WebAPI reads as "He's rather have XML than JSON; give him that".Hence your result vary depending on whether you use IE or Chrome.
Originally posted by @jamescurran in aspnet/Mvc#1765 (comment)
@jamescurran this used to be the case but not anymore.
(很优雅的处理方式,解决了浏览器
*/*
调试api问题;因为正常请求不会有*/*
header, 故检测到有*/*
直接去掉negotiation,取默认的formatter)There is still content negotiation going on based on the runtime type of the object, so the first formatter than can handle the type wins.
The jist of this design is that browsers hitting an api are not really opting into content negotiation, it is more of a way to test an API (not the right way, but a very convenient way). So we would like a consistent experience. A client on the other hand will (should) never provide a
*/*
, as a*/*
is implied anyways.Originally posted by @yishaigalatzer in aspnet/Mvc#1765 (comment)
The text was updated successfully, but these errors were encountered: