In previous milestones, MVC's JSON serialization used Json.NET's default naming convention. This maintained C# property names in the JSON.
In 1.0.0, MVC uses camel case names by default. This matches most JSON naming conventions.
Applications which depend on the exact bytes sent over the wire or that include code such as
``` c#
dynamic d = JObject.Parse(body);
may need to be adjusted.
###### To restore previous naming strategy
If you have case-sensitive clients that cannot be easily updated, change your `Startup` from
``` c#
services.AddMvc();
to
``` c#
services
.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
##### Example
###### Before
``` c#
public class Person
{
public int Id { get; set; }
public string FullName { get; set; }
}
Would serialize to
{"Id":9000,"FullName":"John Smith"}
The same model will serialize to
{"id":9000,"fullName":"John Smith"}
Note the initial lowercase letters.
This is the discussion issue for aspnet/Announcements#194.
See also the original issue we fixed in 1.0.0: #4283
What would this mean if we use a JavaScript framework like Knockout.js to map JSON inputs to view models in our client side code? And is there a way to change this back to Json.NET's default?
@clarkis117 , yes there is :
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
This is already available so you can define your settings right now.
I like this change, but -
I think it needs to be configurable to allow developers to choose the serialization naming convention to be used.
@brent-russell this is configurable ;)
@brent-russel, as @sandorfr showed, this is quite configurable. What exactly is missing from your perspective?
@sandorft @dougbu Oh, that's great!
Just communication and documentation then I guess. The announcement didn't hint at configuration at all. Most other announcements that introduce breaking changes provide instructions on how to implement or obtain pre-existing behavior.
Thanks!
hmmm ... I use typescript and tools like create intellisense file from web essentials to map automatically a csharp in the backend to a interface definition in the client.
If you use whatever tool to make automatically server-client entities in typescript, this way by default are not going to work
@lucamorelli Yes, this is one of the problems that I foresee running into with using Typescript tools like Typewriter. Potentially I'd have to change to change parts of my Typewriter model generation code to camel case, which would break significant portions of the manually written client side code.
I really don't like this change, it will effect thousand of developers. I suggestion some feature like this:
``` C#
[camelCase] // provide by json.net
public class Person
{
public int Id { get; set; }
public string FullName { get; set; }
}
```
this will give us more controllable of our code.
Json is not javascript, and it not only use by javascipt. It's a data formate now use in many languages,
Please rethink about it.
@John0King As shown above, this is already controllable. You can always revert to the old behavior if you prefer that, or go the explicit route and annotate the class with serialization attributes.
This change of the default behavior does make a lot of sense. Most other languages nowadays consistenly prefer camel casing for all members; it’s just C# that’s odd here with its pascal case properties. So languages consuming JSON are more likely to feel familar with camel cased JSON properties.
I welcome this change, thanks!
@John0King from my experience the Attribute thing is to be kept minimal, it's easily forgotten. The way to go is AddJsonOptions.
For the "I like this better", I personally don't care, but I think using AddJsonOptions should be a recommend practice not matter you want the default or another behavior.
Looks good to me. Saves having to set CamelCasePropertyNamesContractResolver in Web API.
Here is an example of doing this from the old Web API on the full .NET Framework, but I'm planning on porting this to Core after it RTMs.
Buggah... I suck at life, and replied to the wrong thread on #4283. Boh.
Anyways, I again find myself in the minority here. I also believe I speak for a lot of the native/Xamarin/enterprise developers that wish to keep consistency between code (C#) and the data that represents that code.
I would feel better if this change default was hinged to a particular "style" setting/attribute somehow, meaning that in native/enterprise applications, PascalCase is the default, and in web applications camelCase is the default.
It basically is, though. It's literally one line of code to switch it
around.
On Jun 10, 2016 8:49 AM, "Mike-EEE" [email protected] wrote:
Buggah... I suck at life, and replied to the wrong thread on #4283
https://github.com/aspnet/Mvc/issues/4283. Boh.Anyways, I again find myself in the minority here. I also believe I speak
for a lot of the native/Xamarin/enterprise developers that wish to keep
consistency between code (C#) and the data that represents that code.I would feel better if this change default was hinged to a particular
"style" setting/attribute somehow, meaning that in native/enterprise
applications, PascalCase is the default, and in web applications camelCase
is the default.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/aspnet/Mvc/issues/4842#issuecomment-225186624, or mute
the thread
https://github.com/notifications/unsubscribe/AAavtJZY3M0r8OFfYHyUPPNBLU0OeC8Sks5qKWtVgaJpZM4IyfXK
.
Yes indeed @ciel I understand that, but what this decision says is that by default the camelCase is the better/preferred format, whereas PascalCase is not. So what does this say about C#, upon which (ironically) the serializer is written in?
This introduces confusion and context-switching into the process. I hope that you can understand my viewpoint and concern here.
I understand your standpoint and concern, and to an extent I share it. But
I also see the ease of switching makes it a non-issue overall. It could be
even further remedied by just including the code to control the format as
part of the default templates.
On Jun 10, 2016 8:54 AM, "Mike-EEE" [email protected] wrote:
Yes indeed @ciel https://github.com/ciel I understand that, but what
this decision says is that by default the camelCase is the better/preferred
format, whereas PascalCase is not. So what does this say about C#, upon
which (ironically) the serializer is written in?This introduces confusion and context-switching into the process. I hope
that you can understand my viewpoint and concern here.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/aspnet/Mvc/issues/4842#issuecomment-225187992, or mute
the thread
https://github.com/notifications/unsubscribe/AAavtK-sPphSFo0gUngfnPV2Foy7oE8fks5qKWyegaJpZM4IyfXK
.
I don't think it is a good or wise decision. But, I also don't have my
fingers in dozens of projects. I have faith that the people who do made
this change for a good reason. That's all. I'm not discounting what you're
saying.
On Jun 10, 2016 8:56 AM, "Stacey Lynn" stacey.cielia.[email protected] wrote:
I understand your standpoint and concern, and to an extent I share it. But
I also see the ease of switching makes it a non-issue overall. It could be
even further remedied by just including the code to control the format as
part of the default templates.
On Jun 10, 2016 8:54 AM, "Mike-EEE" [email protected] wrote:Yes indeed @ciel https://github.com/ciel I understand that, but what
this decision says is that by default the camelCase is the better/preferred
format, whereas PascalCase is not. So what does this say about C#, upon
which (ironically) the serializer is written in?This introduces confusion and context-switching into the process. I hope
that you can understand my viewpoint and concern here.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/aspnet/Mvc/issues/4842#issuecomment-225187992, or mute
the thread
https://github.com/notifications/unsubscribe/AAavtK-sPphSFo0gUngfnPV2Foy7oE8fks5qKWyegaJpZM4IyfXK
.
Also, the general naming convention for data names in json on the web now is snake_case, and not camelCase. Seems a little weird to set the default to be something that is in the middle of the c#'s naming convention, and the most common json naming convention.
That's all. I'm not discounting what you're saying.
Cool thank you for that @ciel. :)
And yes, I can see why it's a non-issue. I mean, people say the same thing about xml vs. json. :wink: To me it all comes down to consistency. That is why I wonder if Xamarin/enterprise side of the aisle was consulted with this as this makes their (or our :smile: ) side inconsistent by default now.
Seems a little weird to set the default to be something that is in the middle of the c#'s naming convention, and the most common json naming convention
I hear you @0xdeafcafe (awesome name btw LOL!), but what we seems to get lost here is that there is a history and legacy -- not to mention an entire _enterprise_ -- that you also have to consider here with MSFT. This should be the learning lesson of project.json (as I tried to point this out back in the day, as well).
By itself, in the ".NET Core" or "web" way of things, this makes sense. But when you shine this through the prism of MSFT's history and other commitments, you run into problems.
I think this just goes to further the need to recognize the schism/chasm that is within MSFT at present: enterprise (legacy/native) and web (new and shiny). I don't want to infringe upon your standards (or creativity/innovation as what is going on here is great!), but let's not infringe upon others while we're at it.
@Mike-EEE I guess, I just don't get why they didn't leave it as is, and not annoy anyone (as we're all used to writing custom converts/setting attributes/custom serialization settings). Instead of changing it to something in the middle that is just going to irritate both sides, and only really please those few in the middle. On top of that, most "enterprise" companies either don't use JSON, or use PascalCase if they do.
You know @0xdeafcafe ... I actually just re-read what you wrote and have to say that I totally misunderstood you! Yes, you are correct. This does seem to be a "middle" ground play, for lack of a better word.
And the web evolves so fast, who knows what format will be the flavor of the month, next. :wink:
Most "enterprise" companies either don't use JSON, or use PascalCase if they do.
Very true! We should say they don't use JSON... YET. As .NET Core moves towards making this a requirement. :stuck_out_tongue: But I am very much a proponent of enabling developers and organizations to "bring your own serializer" and allow them to use the data formats (and corresponding tools) that make them the most productive. A notion that hasn't quite caught on here yet.
My position is that all decisions should "protect the investment" and brand of MSFT. That means innovate and appeal to other methods/technologies (as VS Code is doing a great job of doing), but do so in light of the history and tech that got us here.
This change is _probably_ correct. However the execution of this is absolutely insane. Right in the middle of RC2 and RTM is when you decide you're going to break every single application that uses C# Pascal cased property names because that's what the data serialized as.
Is this the decision making process going there?
Although the new behavior is what I'd like by default and this change would be reasonable in the beta fase, I don't think this kind of change should be done now (RC to RTM).
Indeed, it's very easy to roll back to the previous behavior, but you are requiring every application do to it. Plus, it's not hard to change to camelCase now.
I think the aspnet team should consider the impact of requiring every app out there to do it and other breaking changes like that.
Upgrading our app from RC1 to RC2 was a PITA. Among other things (like tooling, defaults, namespaces, etc.), we couldn't made our migrations work without deleting them all and creating again. We read the docs (which were very helpful), but it's a lot of work that don't necessarily add real value to our app.
I really hope that upgrading to new versions will be more easy to do than RC1 to RC2. We're not in beta anymore, we should be more restrictive in breaking changes. It's not even close to semver.
Updated description to show the configuration one-liner.
Hi all, this is indeed a significant change at a late stage in the product. No doubt about it. We've been working with @JamesNK (author of Json.NET) on this change and this is the quickest we could get it done. And it's pretty much a "now or never" kind of change. We recognize that this type of change can be painful for early adopters such as those here on this thread.
We feel that it is the right overall thing to do for the product, and though there is some short-term pain, there are long-term benefits that outweigh it. The general consensus on both this issue and on the original issue requesting the change (https://github.com/aspnet/Mvc/issues/4283) is quite clearly in favor of this change. We of course announce these types of breaking changes on the Announcements repo to mitigate the pain. And thanks to a simple, straight-forward design in Json.NET and ASP.NET Core MVC, it's quite easy to change the behavior back.
Thanks,
Eilon
Thank you @Eilon for taking the time to explain this. My concern of course still stands, and it doesn't seem like you spoke to it, unfortunately. Timing aside, can you speak to why you are choosing to inject a fundamental inconsistency in casing defaults between code and data for .NET solutions? I understand that there was a general (overwhelming, even!) consensus in favor of this direction, but that was the case for project.json, too. :wink:
(too soon? haha)
can you speak to why you are choosing to inject a fundamental inconsistency in casing defaults between code and data for .NET solutions?
No good deed goes unpunished.
can you speak to why you are choosing to inject a fundamental inconsistency in casing defaults between code and data for .NET solutions?
No good deed goes unpunished.
My thoughts exactly
Hahaha... geeze, tough crowd. Although I shouldn't be surprised. I concede that I am in the minority here (at present). Again, if all of your great work here was done in a vacuum this all makes sense and no problem. But unfortunately since this is under the MSFT brand we do have to lend consideration to legacy/history and overall ecosystem. These are exactly the same concerns I expressed with project.json over a year ago and no one paid notice to (or flat-out disregarded) my input then. And wouldn't you know it, they eventually bore out into the costly about-face we're all (or really, you all :stuck_out_tongue: ) are having to endure at present. Maybe I will be patient and wait another year before someone with some clout can reverse the course of this questionable decision, too. :stuck_out_tongue:
@Mike-EEE My problem is that from my prospective this happened out of the blue. I understand that there were a significant number of core collaborators involved in the decision making process for this; however, it is a significant breaking change. For context, when I first saw the announcement issue it didn't even have a breaking change label nor the options code snippet to change it back.
I was also unware that camel case is the "convention" for JSON data naming. I even went as far to talk to some friends who are now enterprise devs working with other web stacks, and even they were unware that camel case was the "convention". The feedback I got was it was whatever naming convention they were using for objects in their code was the same convention they were using for JSON.
In addition, this has to be in the documentation for MVC. I remember starting out with MVC over a year and a half ago and expecting it to respect the naming conventions that I used in my code. Therefore, I strongly feel that this should be added to the documentation; that by default MVC won't respect the naming conventions you used for your objects. This could be a potential point of frustration when onboarding new developers, as many people have said, paraphrasing, the defaults are important for an ecosystem... and if they suck it's a major turn off. For example, all the people who advocated for this change have enough experience and knowledge to know what value it may add to the ecosystem/product, but beginners will definitely not know that information. I myself still don't know the value this change adds other than supposedly everyone else is doing it.
Thanks for explaining @clarkis117. That is some really great feedback and insight.
From my perspective, this issue is complicated by three factors:
While your concerns are primarily short term (and it's great to see you appreciate the long-term as well), I think this goes to show that we as a community need to start thinking in terms of profiles when we design features -- at least in the short to medium term. This approach is not unlike the coding profiles you are introduced with in Visual Studio when you first install it. This, however, affects the actual code and how it is initially configured before you actually get to coding it.
So in this case if you are a "native" developer, you get PascalCase by default, and a "web" developer gets camelCase by default. And a "hack" developer gets snake_case. I kid I kid... sorta. :smile:
Ultimately, however, the (long-term) root of the problem is that we are touching JavaScript (or non-MSFT/.NET languages) at all. In fact, ASP.NET is the only primary product/group in MSFT that introduces and _requires_ JavaScript for .NET applications, which is extremely disruptive. What we should really be focused on is bridging the divide between "native" and "web" developers so that we are all working from the same conceptual client development model and as a result from top-to-bottom, through-and-through, we are all using the same constructs and idioms, and therefore, conventions.
Call me an idealist, though. :smile:
Again, if all of your great work here was done in a vacuum this all makes sense and no problem.
The irony here being that PascalCase _is_ the result of decisions in a vacuum. Looking at literally the rest of the world, and seeing that you're doing JSON in what amounts to a proprietary way, should give pause and invite change. Not more myopia.
Not more myopia.
Haha! Well again I am seeing your side, but it doesn't sound like you are seeing mine. Well really not mine, but over 15 years of yes, living in a vacuum. You're not really speaking to me, but hundreds of thousands of .NET developers and organizations who have spent their time loving their vacuum-sealed paradigm.
This is this _history_ that continues to seem lost with some of the decisions made here. I say some because what has been accomplished here is really great. I am definitely a fan and big supporter. .NET needed something like this in a big way. We simply need to find a better way to make the decisions that "play nice with others" (e.g. EVERYONE ELSE BUT .NET LOL) gel well with the rest of the ecosystem that this product is a part of.
I am definitely open to ideas and dialogue here, I hope that is clear!
JSON in what amounts to a proprietary way.
Is that before or after we modified the serializer to accept inline comments? :smile:
Well again I am seeing your side, but it doesn't sound like you are seeing mine. Well really not mine, but over 15 years of yes, living in a vacuum. You're not really speaking to me, but hundreds of thousands of .NET developers and organizations who have spent their time loving their vacuum-sealed paradigm.
I do see that side - .NET Core had brought it into sharp focus.
If we'd done things the way they'd always been done, we'd still be squatting in the woods. There will always be those squatters for whom change is simply what jingles in their pockets. The world has gotten bigger since 2001; like it or not, the ostrich defense is paying less dividends now.
Optimizing for those static opinions, those immovable rocks in the river of innovation, is a recipe for staleness and irrelevance. Weep for those losing their capital letters; lament the death of their representational privilege; then step aside and let evolution happen.
Dang @bwatts that has got to be the most metaphoric reply/answer/contribution I have ever seen in a discussion. Ever. Kudos to you, sir. :+1: :smile:
Also, there's an inherent naming disparity in the options setting now. If the default is now camel case and you're telling devs to set it to something with default in its name inorder to change it back; some are going to look at that and say, "bro, can you even name" :p
I must say I agree with the points raised by @Mike-EEE and @clarkis117 .
@obraunsys
camelCase is not a JSON naming convention. it's a Javascript naming convention.
So nothing to do with JavaScript Object Notation? Ok... :wink:
@MaximRouiller
You are of course right about the origin of the name, and I know this statement can be controversial (which is why I started with "in my opinion"), however, I would argue that JSON has become a language-agnostic serialization format.
Please note that I agree that camelCase is the proper format when using JSON with JavaScript, but some of us also work with C# code on both sides of the pipe, and I have never seen anybody use camelCase in this situation (not saying it doesn't happen, I just haven't worked on any project where this was required or desired).
@MaximRouiller
So nothing to do with JavaScript Object Notation? Ok... :wink:
It's based off of JavaScript, but there is no official naming convention definied in the JSON spec. The fact of the matter is, It's entirely up to your use case/preference.
However, as I previously said, I think it was a bad idea to make this change. Keep it PascalCase by default, as that's the languages naming convention. Let people apply custom rules as and when they see fit. This is just going to cause a literal fuck-ton of questions on SO, as newer people move to this framework and start wondering why their API is outputting data that doesn't reflect the format of their data/view models.
@0xdeafcafe
As with every breaking changes, if we don't change it now... when will we? Probably never.
The good news is that new development will adopt the camelCase and those in a different casing scenario are literally just one line away from reverting back to the old behavior.
Damned if you do, damned if you don't. It's been the same reaction from everyone for everything that moves a previous default.
@MaximRouiller
I agree that now is the time to introduce breaking changes and start with a clean slate, but this is probably the wrong default for .NET serialization.
As with every breaking changes, if we don't change it now... when will we? Probably never.
While I respect that viewpoint (as it is rather accurate), I would like to point out @obraunsys's excellent observation about WebAssembly (which is really the "missing link" from a ubiquitous .NET client development model). Once that kicks in this issue will indeed be a thorn in our collective sides.
There are, however (trying to be objective here -- and also maybe beat an objector to the punch :grin: ) a couple considerations:
@Mike-EEE
So the positions against are the following:
Problem: We already have apps that use PascalCase!!!
Solution: One liner to change the default. People go back to life a happy and uneventful life.
Problem: It should be up to us to decide!
Solution: You already are. The defaults are just changed and can be changed.
Problem: WebAssembly might be a thing within the next 5 years. Let's no hurry too much.
Solution: Unless it's shipping now (or the next 6 months) and an issue in the very near future, let's not worry about this. Otherwise, we end up in a paralysis in case something important might be hindered by today's choices.
That's it. It's a non-argument. Defaults can be changed. Even in the case of WebAssembly, it's a non-issue since the default can be changed in literally one line.
Hahah I agree @MaximRouiller, it's all so very complicated! :smile:
The biggest problem to me personally (that isn't in your list) is the inconsistency with established (and continuing) standards from over 15 years of .NET development. This change as designed at present simply introduces inconsistency (and resulting confusion) in light of .NET's storied history.
WebAssembly simply adds another dynamic to this, much like introducing a breaking change before RTM. :stuck_out_tongue:
Just think... if MSFT had done the right thing and simply gone the JSIL route rather than trying to introduce a completely incompatible language and client application development paradigm into .NET solutions, we wouldn't even be having this discussion in the first place. #cryingoverspiltmilk :grin:
@Mike-EEE This has nothing to do with "established .NET standards". The rest of .NET can and will go on with its existing defaults. This is MVC, a single .NET-based web framework, changing its defaults. Other frameworks, like Nancy, has changed these defaults a long time ago.
There is, of course, no standard when it comes to JSON property names, but AFAIK, the rest of the (web) world uses either pascalCased (most common), kebab-cased or snake_cased naming for JSON representations. After all, it isn't called JavaScript Object Notation for nothing. Google even has a JSON "style guide" suggesting you use camelCase.
Because we've wanted to follow the rest of the world, we've always been forced to change MVC's defaults, until now. As I mentioned in the other issue that suggested this change; this has always been the first thing I've had to change when setting up every single MVC/WebAPI application I've ever made. It's (about) time MVC changed to a more sensible default. Who do you want to optimize for? The 20% or the 80%?
If you want to use XAML, or keep the "old" defaults, it's completely up to you. These are just defaults, you're free to change them. Let's not keep bad defaults around because of a minority.
The rest of .NET can and will go on with its existing defaults
You mean with its existing _inconsistent_, _conflicting_, and _contradictory_ defaults.
Google even has a JSON "style guide" suggesting you use camelCase.
Does that same style guide suggest comments in its JSON? :angel:
I mentioned in the other issue that suggested this change; this has always been the first thing I've had to change when setting up every single MVC/WebAPI application I've ever made.
And who's fault is that? :smile: Again is this a MSFT product or a product that is developed outside of MSFT? If it's a MSFT product, it should (ideally) adhere to MSFT standards, of which we know that PascalCase is indeed the default casing for all of .NET's languages. Getting back to the unfortunate developer divide we find ourselves in, if we never had to deal with JavaScript, we never would have to deal with this discussion. This is the _only_ product/project/group that requires JavaScript for proper operation. Now it seems all other MSFT groups/products/projects will suffer from an inconsistent default because of it.
It's (about) time MVC changed to a more sensible default.
It's about time MVC ditched the JavaScript. :stuck_out_tongue:
If you want to use XAML, or keep the "old" defaults, it's completely up to you. These are just defaults, you're free to change them.
The same case can be made for the reverse. :) And they aren't just old defaults, they are established and ingrained. This whole issue/approach/attitude sort of makes me want to say "MAKE MSFT GREAT AGAIN" or "MSFT First" as what is taking place here certainly isn't that. :stuck_out_tongue:
Again, this is a MSFT product based in MSFT history and this must be accounted for when considering these sorts of changes. Has project.json taught us nothing? :stuck_out_tongue: :stuck_out_tongue: :stuck_out_tongue:
Is it possible, _just possible_, that the .NET renaissance could lead to an increased awareness of other communities? Perhaps we could admit that perpetuating cultural ignorance (in this case, the culture around JSON) might be counter to the strategy of an inclusive .NET?
@khellang, I agree that the reason for the change (it's what you want 99% of the time), is a damn strong argument.
I guess some of us have PascalCase ingrained in our brain when working with .NET and the new default will feel wrong, but the final decision should be what is best for the ASP.NET Core MVC ecosystem.
Just wanted to put my 2¢ in and voice my concerns regarding this decision.
Have a nice day guys!
I am reading this thread and I am thinking: Whats the big deal? All options are still available.
If I had to issue an opinion: JSON is based on Javascript and it makes sense to follow the dominant conventions in the Javascript world. It is irrelevant between which types of systems JSON is used for data serialization.
@Mike-EEE
You mean with its existing _inconsistent_, _conflicting_, and _contradictory_ defaults.
Why should there be _one_ default for _all_ of .NET? The way it is today, on the web, .NET is the odd one out.
Does that same style guide suggest comments in its JSON? :angel:
Why would it? There's no comments in the JSON spec.
It's about time MVC ditched the JavaScript. :stuck_out_tongue:
I really don't know what to say here... It seems you've been living under a rock (or at least far away from the web) for a while :stuck_out_tongue_closed_eyes:
I see your argument though; why can't we just close out the rest of the world and live in our own warm and cozy little .NET bubble? Let's see how long that lasts. People are already fleeing :smile:
The same case can be made for the reverse. :)
But in your quote, you left out an imortant part:
Who do you want to optimize for? The 20% or the 80%?
Do you want to stick with the existing defaults and force 80% of people, maybe also coming from other languages/stacks, to change them? Or do you change the defaults and make the remaining 20% change them?
Again, this is a MSFT product based in MSFT history and this must be accounted for when considering these sorts of changes.
If we'd stuck with MSFT defaults and MSFT history, we'd still be sabotaging the web with IE6. Let's not forget and instead learn from history.
Has project.json taught us nothing?
I don't think (reverting) project.json ever was about angle brackets vs curly braces, so I'm not sure what it has to do with this... All its keys were camelCased. Are you saying that's why we're going back? Cause that would be pretty naïve.
Whats the big deal?
It's the principle of the matter. :)
JSON is based on Javascript and it makes sense to follow the dominant conventions in the Javascript world
Again this makes sense if you are building a non-MSFT and non-.NET product that has nothing to do with C# or anything .NET-related. However (and unfortunately) this is not the case as .NET Core is indeed attached to all of the history of .NET and MSFT.
project.json was a good example of this.
Why should there be one default for all of .NET? The way it is today, on the web, .NET is the odd one out.
100% correct if you look at it from a web-perspective, 100%-wrong if you look at it from a .NET (native/enterprise) perspective. :)
Why would it? There's no comments in the JSON spec.
100% correct, yet we have modified/adjusted JSON.NET and project.json to allow them (this was a prod towards deviating from standards, that obviously didn't take!).
I really don't know what to say here... It seems you've been living under a rock (or at least far away from the web) for a while :stuck_out_tongue_closed_eyes:
Hahaha... no I have been having to endure putting up w/ HTML5/JavaScript polluting our ecosystem since Silverlight bit the dust. :smile: ... or i should say: :frowning: :frowning: :frowning:
why can't we just close out the rest of the world and live in our own warm and cozy little .NET bubble?
While simultaneously reaching out to and embracing external developers, technologies, and communities. I agree! It's much easier said than done.
Do you want to stick with the existing defaults and force 80% of people, maybe also coming from other languages/stacks, to change them? Or do you change the defaults and make the remaining 20% change them?
Well who is the 80%? From the web/adoption perspective the 80% is the webdev/JavaScript/HTML5 "web designer" crowd (that Visual Studio Code targets). From the historical MSFT perspective, 80% would be the native/enterprise crowd. Guess which one of these has put hundreds of millions (if not billions) of dollars into MSFT's coffers? :)
If we'd stuck with MSFT defaults and MSFT history, we'd still be sabotaging the web with IE6. Let's not forget and learn from history.
Fair enough (dang you bring up great points! I haven't quoted so much on GitHub as this post). I suppose I should have said MSFT .NET/Developer history. This has been very successful and has done much better than IE6 and a lot of other products.
Are you saying that's why we're going back?
project.json overlapped with MSBuild and Visual Studio tooling in so many ways. This has been and was brought up for more than a year as votes and with issues in associated repos (example), but were essentially disregards and ignored. It wasn't until the Xamarin acquisition and the enterprise groups starting to catch wind of project.json did everyone suddenly realize that there were a _lot_ of scenarios (read: history and legacy) to account for that project.json simply did not fulfill, hence the reversal.
I am using that as a premier example of saying that the efforts done here impact more than just this project, and we should be mindful of the entire .NET developer ecosystem and be considerate, accordingly.
100% correct if you look at it from a web-perspective, 100%-wrong if you look at it from a .NET (native/enterprise) perspective. :)
Last time I checked, MVC was a web framework.
I'm out :wave: This thread makes me want to leave .NET :sob:
Last time I checked, MVC was a web framework.
A _.NET_ web framework, written in .NET languages (which follow .NET guidelines). :)
This thread makes me want to leave .NET :sob:
:frowning: Really appreciate the dialogue and thoughts, though. :+1:
I was thinking maybe this should be red:

Folks, at this time we are not planning to change this decision. We feel we made the decision that overall makes things better for ASP.NET, MVC, and .NET. For those who are negatively affected by this decision, it's a simple switch to change the behavior back:
c#
services
.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
Given that we are not changing the behavior, we would like to keep this thread focused around the change, as opposed to whether it's a good change or not.
CamelCase PascalCase I really don't care, I think the goal is to get the data I want, if the client need camelCase ,then give it with camelCase, if client need PascalCase then give it with PascalCase , if client need both , give it with the the client need, someone like( or need) camelCase you can write camelCase Object or Use [JsonProperty("myName")] on MyName property .
Now default behavior is to convert the code you write and into something else, It's like you write game, when press up key, player go up,press down key,player go down, but when you run this game, you press up key ,player go down, is this really you want to be with you in next 10 years ?
someone also say other language all use camelCase json , I'm not a expert but is there any language serialize json won't use the same name as you write? And i'm sure it will generate PascalCase json when you write object in PascalCase.
Other side: if you write a C# object
``` C#
public class MyData
{
public string WWTUrl { get; set; }
public string W3CUrl{ get; set;}
}
serialize to
``` json
{
"wWTUrl":"http://www.worldwidetelescope.org/",
"w3CUrl":"http://www.w3.org/"
}
Is that will feel good ?
sorry for my bad english
For those who are negatively affected by this decision, it's a simple switch to change the behavior back:
Totally missing the point here. :) But that was the case for project.json as well. Sooooo... I will just let it ride until someone with a little more clout than little ol' me sees the same thing and interjects.
we would like to keep this thread focused around the change
Well, if you insist. What about the now odd/awkward position of having DefaultContractResolver no longer being default? Seems like there are two breaking changes here as DefaultContractResolver will have to be renamed.
What about the now odd/awkward position of having DefaultContractResolver no longer being default?
Talk to @JamesNK? or do a pull request? :stuck_out_tongue:
Well, I'm at least happy that I won't have to configure all of my projects to use a community-friendly JSON style. The looks I got from front-end devs the first time they saw my PascalCase JSON, yeesh.
If you are on the web then camelCase is the accepted standard; if you are in a closed system you can change the default, can also happily use the xml serialisation if that's your thing.
If you are not on the web generally interconnected systems are now no longer homogeneous and written in one language or on one O/S; so you don't want .NET backed apis to standout as the incongruous ones.
If you are exposing your apis publicly, or hope to do one day, you definitely want camelCase as you can't and shouldn't determine your customer's choice of language or development tools - unless you want less customers - so I applaud this change.
In every project I ever worked in, all frontend devs has DEMANDED camelcased JSON, so I really like this decision, great work.
@Eilon > Given that we are not changing the behavior, we would like to keep this thread focused around the change, as opposed to whether it's a good change or not.
So where do we take up our issues with _the how_ this change was done out of the blue and immediately before "RTM"? Or were you directly telling us to shut up?
@dotnetchris the change was discussed starting on March 14th, which is nearly 3 months ago now: https://github.com/aspnet/Mvc/issues/4283, and got near-universal support from the community (over 100 upvotes, which is more than any other issue in all of 'aspnet').
Then, 19 days ago, I mentioned that we decided to take this change.
Then, earlier in this thread I gave further reasoning for why we did this change.
This thread as well also shows that people are overwhelmingly in favor of this change.
We know we can't make everyone happy, but this change clearly makes more people happy than sad.
Thanks,
Eilon
I appreciate your time in taking a moment to express the reasoning behind this, @Eilon. It really means a lot.
My primary concern here, and I will simply say this and shut up (well OK, probably not. :grin: ) is that this change affects much more than this repo/product/project. Of course it is going to have high marks here, (much like project.json did/does), but externally, it might not do so well. As long as you understand that and you have heard me, then I can feel better about accepting this. :)
@Eilon You know what makes me happy? Clicking on all the positive reactions below your comments.
It will finally make it easier to integrate with AngularJS/KnockoutJs/[insert other JS framework] in the future. Thanks for making this decision.
@Mike-EEE After double checking, this will not impact you unless you are parsing JSON by hand.
If you are using JSON.NET to generate/parse your data? No impact what so ever unless you are serializing Dictionaries. Assuming that behavior hasn't been fixed already.
@MaximRouiller Can you please explain what you mean by parsing by hand? As in it will only affect my files if I am editing them and not using the serializer to create them?
And no, I don't use JSON. I avoid it as much as humanly possible. I am all Xaml all the time 100%. :) Again, to me this is the principle of the matter, and I am also trying to speak for enterprise/native developers as well. Guess they will just have to chime in at a later date. :open_mouth:
@Eilon so the first time i heard of this was when the aspnet announcement appeared in my git inbox. How would i have been made of aware of this sooner that I could have actually provided feedback prior to the final decision being made? It doesn't seem like anyone in this thread expected this decision and that everyone was surprised. There's clearly a gap here.
@Mike-EEE this is about the property casing used specifically for the JSON serialization format used over http/https when used via Web Api.
You can also use XML as a serialization format among others and that will be unaffected by this change.
If you are not consuming web api REST endpoints, you will also be unaffected by this change.
@dotnetchris
@Eilon mentioned that it was talked about 3 months ago.
If you want to get part of the discussion, you can subscribe to this repository and get in on the discussions!
@benaadams and @MaximRouiller (and really everyone haha) OK I am with you now. Thank you for your patience and great dialogue!
@dotnetchris all discussions related to the MVC product tend to happen right here, in the MVC repo. The Announcements repo is for things that have happened, whereas the individual "product" repos are for work we are planning and debating.
@Eilon what's the purpose of these discussion threads at all if everything is a done deal and the ship has already sailed? the way i originally understood the purpose of the announcements repo was to put a much more curated feed out. It seems largely, if not entirely, pointless given this thread.
What purpose does this thread at all serve? What is there to discuss if announcements mean "this is it"?
The announcements issues might as well say "these decisions were made, you missed your chance to provide feedback, no discussion"
Also @Eilon please make sure you point a Micrsoft PR / Evangelist or whatever is the correct responsibilities at this thread. The current process of the announcements seems broken by design.
@dotnetchris as I mentioned several times now, this change was discussed at length for nearly three months before making the change, and for a few weeks once we committed to making the change, and only then did we actually make the change. I'm not sure what you're asking us to do differently in the future.
I'm sorry this change doesn't sit well with you, but I feel that we followed an open process for making this change: we listened to what customers asked for, over one hundred people were in favor of it, almost no one was against it, and so we made the change. We discussed the change with @JamesNK , the author of Json.NET, and a well-recognized figure in the community, and even got a new feature in Json.NET that would make this a safe change to make. And as we see in this thread, it seems to me that most people also agree that this change had sufficient visibility and awareness prior to it being made.
We encourage open participation in this project by monitoring the specific product repos (MVC, EF, Razor, Kestrel) and adding comments and voting on issues.
We understand the open process @Eilon (now :smile: )... but it does seem that creating a discussion thread after the fact is a little late in the process (or really, not very valuable at all) -- as there really isn't anything to "discuss" outside of patting ourselves on the back. I think what @dotnetchris is suggesting is perhaps tweaking the process/workflow here so that the community can provide more/better input sooner.
It's a tricky problem, as I personally do not subscribe to these repos (there are a LOT of notifications, as you well know). However, I do subscribe like a monster to RSS feeds to pretty much every MSFT blog there is, so that is how I get my information. If there was an announcement to discuss a breaking change on a blog post I would see it, FWIW.
It would be even better if GitHub provided an alert or "critical notification" that also allowed us to know when super important issues are going down, as well.
@Mike-EEE Currently, it's everything or nothing.
If you watch a repository, you'll be informed of every event on any issues.
This is a GitHub issue. By experience, blog posts are just like "announcement" but with less detail than what we find on GitHub.
Yeah I hear you @MaximRouiller, just expressing some thoughts. Not saying I have the answers, just suggestions. I am curious on how many notifications this repo sends out a day. I am already subscribed to a few and it's quite chatty. Basically goes straight to a outlook rule. :stuck_out_tongue:
I am personally only watching Announcements.
I do not have enough time to participate in design discussions. I believe that the .NET Team will deliver a workable product that will build upon standard, common practice and good faith.
So when something as simple as a default is changed, I don't blink. Not until we hit RTM and they deliver 1.0.1.
Yeah same... I do have Announcements watched, which is what landed me here. The suggestion/ask/desire here is to get a "Pre-announcement" mechanism where we can somehow join the conversation before it gets to this point, but I am not sure that is easy/possible ATM.
@Mike-EEE
Then you get to the problem where it's decision by committee where the committee might not even contribute (or be able to).
If you exclude design by committee, you end up with a repo that is used for asking if it breaks anyone and you don't need a repo for this. It will always break someone. In any scenario, I'll trust the team until they go crazy. Then, I'll speak. I don't have time for anything else.
Also, what qualifies for a "pre-announcement"? Sorry @Mike-EEE. Either you get involved (watch the repo and give feedback), or you don't. Simple as that. It's the same for everyone, like the hundreds of people that left feedback on the original proposal.
LOL geeze duders, I'm looking to help out here. The goal/ideal here is to get visibility to changes that people may or may not be interested in. If there are 100 people that like an issue, but there are really more like 500 that don't like it, this might be valuable to know. It's basically improving/increasing visibility of important topics without increasing noise to the average user. This is not asking for more cooks in the kitchen (design by committee) but more visibility which leads to more participation (think: GitHub reactions/votes rather than long exhausting threads like this one for the most part -- ideally), which leads to happier developers which leads to happier community which leads to a better product.
In theory. :smile:
@Mike-EEE
With what happened to https://github.com/aspnet/Home/issues/1433, I believe that there will be too many cooks in the kitchen. Or at least, lots of sideline coach. Each wanting to contribute, but lots of them not having a complete big picture and none doing any actual basic Proof Of Concepts or Pull Requests. And that is if they even installed the actual framework.
So let's retake the same scenario. Change of default to the JSON Serializer. What would a discussion on the subject would have look like? I'm not sure but I'm betting lots of people would have said exactly what was said here. We would either still be discussing it or it would have been approved anyway and people would have complained that Microsoft wasn't listening to comments.
tldr I'm ok with how things are.
I understand your concern @MaximRouiller. I hear you haha. The difference between what we have now and what we're discussing is that we would have dialogue BEFORE any changes were made, rather than after. I would feel better if:
1) I knew before I jumped into this discussion that it was "already too late" for any sort of change.
2) I knew beforehand there was some way of voicing my concerns (or more importantly in my mind: votes/reactions -- ala GitHub reactions, which at present is the greatest instrument for measuring sentiment) about this issue before it was sold and set in stone.
I'm OK with having my vote rejected, as long as it is heard. I am not OK with not having my vote utilized or counted or making it in the tally in the first place -- regardless of the reason. We can chalk it up to my ignorance (lack of tooling/notifications), or poor process, but the fact that my vote (or anyone's vote) didn't make it into the final tally is really what should be the focus here, and what I am driving at.
Again it is all about promoting awareness and participation so that as many metrics as possible are provided to the stakeholders and drivers to the repo. Hope that clarifies my position. :)
@MaximRouiller @Mike-EEE Do I hear a need for a discussion on changing the default serialization format for Web APIs to Protobuf? ;-)
@Elion I added suggestion to https://github.com/aspnet/Home/issues/1571 on a way to make breaking changes more visible while they are still at the "potential" stage
@Mike-EEE would that help?
@Mike-EEE would that help?
Does it ever! Thank you for pointing that out, @benaadams! And thank you, @Eilon!!!
It's ok to have the serializer configurable, but, it sounds weird to be forced to tweak the configuration when you want to use the default configuration of the serializer (DefaultContractResolver).
It would be far more intuitive to tweak the configuration when you want anything different than the default... wouldn't it?
@SocVi100
DefaultContractResolver is only default as far as its name. It was probably called _default_ because it was the default way of serializing in .NET before (think DataContract) JSON.NET became popular.
Maybe we should ask @JamesNK for some history on the naming. ;-)
And yeah... DefaultContractResolver is part of JSON.NET. Not .NET.
@SocVi100 DefaultContractResolver is a Json.NET class, it's not an ASP.NET Core MVC class. I think it'd be better named as PascalCaseContractResolver.
I agree with you... it's confusing.
@fhelwanger the DefaultContractResolver is not PascalCaseContractResolver , you can use DefaultContractResolver to generate camelCased json when you write camelcased C# property or use [JsonProperty("cameCaseWords")] . This is why it called _default_ , because it don't change any thing you write . and PascalCaseContractResolver sound like it will change anything you write to _PascalCase_
@John0King You're right, thanks!
Does some one tested the workaround?
services
.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
It doesn't work in my case for some reason (.net core 1.0 RTM), still have propertyName in JSON. What it can be?
UPDATE: Found the reason, related to Toolling.
@antonGritsenko that's my work around too, working fine for me.
I like this change and I also wrote a little blog so that more people can know about this change.
Blog is here.
@NeelBhatt - I read through your blog, thanks!
camelCase is the default - services.AddMvc() will give you camelCase
If you want the old PascalCase behavior then do
.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
Your blog post seems to give the impression that it's the other way around
@rynowak Thanks for looking into it and for the feedback.
I have updated my blog accordingly.
I just encountered an interesting scenario with camel-cased names and wanted to ensure we account for it.
The default serialization for a Dictionary<,> is to a JSON object:
{ "foo": "...", "bar": "..." }
However, if we serialize an upper-cased key Foo, it will become lower-cased as a property, then deserialize back with the lower-cased name, creating a lossy conversion.
We worked around this by creating a DictionaryConverter that treats dictionaries as List<KeyValuePair<K, V>>:
[
{ "key": "Foo", "value": "..." },
{ "key": "bar", "value": "..." }
]
We wanted to simply tell JSON.NET to use JsonArrayContract for dictionaries, but had to account for existing data that uses the object-not-array format.
@bwatts did you open an issue on https://github.com/JamesNK/Newtonsoft.Json?
If it's a bug, @JamesNK should be informed. I've looked quickly at the repository and it doesn't look like this issue has been logged before.
@MaximRouiller I wasn't sure if it is a bug or just an unfortunate feature collision. I'll open an issue over there anyhow to be sure.
@bwatts @MaximRouiller Camel-case dictionary keys is something that needs to be opted into. If you want to tweak the settings, you can set the JsonOptions:
services.AddMvc().AddJsonOptions(x =>
{
x.SerializerSettings.ContractResolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy
{
ProcessDictionaryKeys = false // this is the default.
}
};
});
As you can see, the MVC defaults are the same as Newtonsoft.Json defaults, which should keep dictionary keys the same.
Thanks @khellang for the clarification! Didn't know about that specific feature.
@khellang I found NamingStrategy and ProcessDictionaryKeys while investigating, but this fiddle seems to contradict that default. Thoughts?
@bwatts Uuh. CamelCasePropertyNamesContractResolver isn't the same as DefaultContractResolver :wink:
This fiddle shows that it works :smile:
I'm using this: http://stackoverflow.com/a/24226442/214073.
Not sure if it's still required, but works.
@khellang isn't the point of the MVC default-to-camel-casing to make the CamelCasePropertyNamesContractResolver the default?
@bwatts No, because as you've discovered, CamelCasePropertyNamesContractResolver also makes dictionary keys camel-cased. That's whay @JamesNK introduced the NamingStrategy class.
MVC uses the DefaultContractResolver with NamingStrategy set to CamelCaseNamingStrategy, which has ProcessDictionaryKeys set to false by default.
@khellang got it - so it seems I shouldn't be using CamelCasePropertyNamesContractResolver at all then. I didn't realize.
This change is really ridicilious. You need to tell mvc to use default serializer to get the default behavior. This is why microsoft is not liked by many.
@gr3ysky The problem is "the default for what scenario"?
It's all a matter of choices.
At least now, we know what the choices are more or less when they happen and we have a way to tailor things to our liking.
The default is the f.cking default. No need to argue on what is default. It shouldnt change the property names. It is just like start menu issue. I have been developing mvc over six years. It was pascal case till now. And just check the code to get old behaviour. And thats silly to say use the default behavior. Right?
@gr3ysky Did you read https://github.com/aspnet/Mvc/issues/4842#issuecomment-228834315?
Further, you're arguing defaults should _never_ change? This is a major version.
First thing I do on every project is change the "default" so I get "proper serialization" for javascript.
What's "right" is a judgement call, not an objective fact.
The new "Default" for serialization in JSON is now lower case.
The model binders for ASP.NET Core will interpret lower-case/upper-case without any issues so this is a non-issue for "current behavior" of the API.
So let's take a look at what scenarios you would need to change it.
Here are the solutions:
It's a major rewrite of a framework. You can't expect to copy/paste your code and expect everything to be feature equal. I have more complaints about EF Core right now than the default serialization for JSON which can be reverted in one line of code. As mentioned before, there's only Microsoft that defaults the JSON serialization to Pascal Case. Now we are "back to normal" in the web sphere.
If you want to go back to the good old days when you are porting an application, here's how:
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
We are closing this issue because no further action is planned for this issue. If you still have any issues or questions, please log a new issue with any additional details that you have.
If I could, I wanted to thank everyone for the respectful and thoughtful discussion on this memorable thread, especially when it turns out I had no idea what I was talking about. 😛 (or to be more accurate, did not completely understand the issue at hand and misunderstood its actual implications).
I'd also like to send a special shout out to @bwatts for his "no good deed" comment above as well. I didn't really understand it at the time, but there have been been numerous instances since then in other discussions throughout GitHub where I have been brought to bear the full appreciation of that statement, LOL. If it helps at all, rest assured that I have gotten my due on the flip side. 😆
Anyways, thought I would share. And no, I can't help it. 👍
It is interesting that if an object is not strong type like object or dynamic, it will not be converted to camelcase. But it can be fixed by
.AddJsonOptions(opts =>
{
opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
Or by using the DefaultContractResolver and setting ProcessDictionaryKeys = true (which I think is recommended):
.AddJsonFormatters(json =>
{
json.ContractResolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy
{
ProcessDictionaryKeys = true
}
};
});
Wow! I found this ugly bug! And it is a really bug!
This behavior broke the data exchange between C# and JS!
1) All properties in JS must be fixed after migration from ASP.NET
2) Doesn't have backward compatibility (to restore broken case) and can't be returned AS IS to the ASP.NET Controller
public class TestModel
{
public int Id { get; set;}
public Dictionary<string, string> Settings { get; set; }
}
Simple method to use model
<script>
var model = @Html.Raw(Json.Serialize(Model)); // case is broken there when ASP.NET Core used
// some methods to bind inputs with model
$('form').submit(function (e) {
e.preventDefault();
$.ajax({
url: this.action,
data: JSON.stringify(model),
type: "POST",
beforeSend: function (xhr) {
xhr.setRequestHeader("Content-type", "application/json");
},
async: false
});
});
</script>
Simple method which must save returned model
[HttpPost]
public ActionResult YmlConfiguration([FromBody]TestModel config)
{
// config = null and NullReferenceException fired there because case broken!
}
It is improbable to change names at serialization! Why?
@QuAzI If you want to restore the older behavior of keeping the casing, see the comments above. They show you many ways to resolve that issue.
Most helpful comment
Folks, at this time we are not planning to change this decision. We feel we made the decision that overall makes things better for ASP.NET, MVC, and .NET. For those who are negatively affected by this decision, it's a simple switch to change the behavior back:
c# services .AddMvc() .AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());Given that we are not changing the behavior, we would like to keep this thread focused around the change, as opposed to whether it's a good change or not.