R.I.P project.json – Out with the new, in with the old An early look at the VS 2017 csproj changes

Okay; the title of the post is a bit tongue in cheek! Since it was first announced that the new project.json format (developed by the ASP.NET Core team) was going to be retired in favour of the more traditional csproj file, the .NET community have had some very strong opinions. These have been shared on Twitter, in blog posts, on GitHub and via any other channels people could find. I will admit that when I heard about the change, I initially had some of the same views and concerns. Why would Microsoft take away my beloved project.json? However, I decided to wait it out and see what Microsoft actually produced before passing judgement.

A little bit of history

Let me take a step back here and try to explain a little bit of the history as I have understood it. In the early beta timeframe for ASP.NET Core (then called ASP.NET 5) the ASP.NET and .NET teams were working independently of one another. The .NET team were working heavily on the API surface for .NET Core, whilst the ASP.NET team were working on the ASP.NET Core application platform on top of the API the .NET team were making. The tooling to work with ASP.NET Core was in an early preview and at the time we had DNVM and DNU commands. These have since been consolidated and morphed to form the dotnet CLI.

In order to support development of ASP.NET projects, the team decided to take the opportunity to develop a brand new project file format. One which would be simpler and address many of the issues the community had experienced when working with csproj based projects. At the time, nothing existed specifically for .NET Core projects and it was felt that since ASP.NET Core represented a new beginning for the platform, it was as good a time as any to make changes. During the betas and release candidates people started to get their hands on the new project.json and xproj based solutions when building their web applications. The response was indeed very positive. project.json provided autocomplete of dependencies, ease of reading and a much simpler overall structure.

Personally, I was very pleased when project.json was born. I could easily understand it and it became a regular reference point to review my dependencies and manage my projects.

However, it was during the release candidate period that decisions started to get made around a wider .NET project format for the other application types. Customers were starting to share their concerns around project.json and the fact that it was not supported within MSBuild. What would this mean for large monolith projects, how would they even begin to migrate them to .NET Core? And, being fair, these were valid concerns. Starting with greenfield ASP.NET Core projects was fantastic. There was no need to concern ourselves with the past and the new new project.json was easy to get to grips with. But, working with an existing project would not necessarily be a simple conversion without some degree of work. So the announcements started to be made that project.json would be retired in favour of a more backwards compatible MSBuild ready, csproj format. It was too late in the day for this work to be completed before the RTM of ASP.NET Core 1.0 but we were warned that it would be worked on for release alongside Visual Studio 2017.

And that brings us to today, with the announcement of the release candidate for Visual Studio 2017 we can now get our hands on projects using the new (or should I say old) csproj project format. I’ve taken an early peek at the file to see what has changed.

Comparing project.json (VS 2015) with csproj (VS 2017 RC)

Microsoft have assured us while working on the change that they expected to port many of the improvements that the project.json file gave developers over to the improved csproj format.

Comparing project.json and the new csproj

In the screenshot above (hard to see due to the size) I’ve opened a default new Web Application project in VS 2015 (left) and VS 2017 (right). Side-by-side the obvious difference in that project.json is JSON and the csproj is XML. You will notice that the line length of the files is not too different. project.json comes in at 65 lines and csproj comes in at 77 lines. Already that is a significant reduction in lines from a traditional csproj file.

Here are the complete files:

The other thing which stands out to me is the readability. Despite the work Microsoft have done to reduce noise in the csproj file, I still find it much harder to scan than the project.json. The XML tags draw my eye away from the detail that I actually want to consume.

At the time of writing I’m still very new to working inside VS 2017 and indeed on my computer it’s proofing quite buggy. For example, a solution that I created inside VS 2017 and which had been working fine (1 web application and 1 test class library) no longer re-opens after I saved and closed it. Suffice to say, I won’t be using Visual Studio 2017 for production work at this time and may even remove it entirely as it seems to be affecting my experience inside VS 2015 too.

Once nice advantage of the csproj file over the project.json is that we can now include references to full (non-core) .NET projects as well. Previously the integration was not available.

Something I do miss however (unless it’s just not working for me) is proper autocomplete of the packages and versions. With the project.json I could start typing the name of a dependency and Visual Studio would show me potential autocomplete options. I could also choose from the available versions. This seems to be absent in the csproj file. Personally I only saw basic intellisense for some, but not all, of the xml tags.

Migrating from project.json

Migration from project.json can be achieved in one of two ways. These easiest is to open the existing xproj/project.json project inside Visual Studio 2017. The IDE will detect the project format and prompt for a migration. The other option is to run the dotnet migrate command directly in the command line. This should result in the same conversion.

Migration from project.json

In a quick test for me, the VS migration seemed to work quite well, although that was a single default web application project with basic dependencies. In theory it should work just as well for larger projects. Perhaps when we come to migrate the allReady project which I contribute to, we’ll see if there’s more to it.

Having done this with the project.json solution created in VS 2015 (as appeared above) we get the following csproj output.

Inside the project.json we have our main dependencies section and inside that we define the package and version. This is pretty clear and easy to read. Inside the csproj each package reference is added inside an ItemGroup element. It’s more verbose than the project.json.

Much of the content is similar and when you compare the files you can generally find where each part has been migrated. However you’ll need to remember the more complex XML schema in order to edit the file manually. Indeed, Microsoft seem to be pushing us away from this in favour of IDE tooling and the command line. I fear though, that those are never going to be as quick to work with as we’ve been used to with a quick edit of the project.json file.

Differences between the original csproj and the new csproj

There are some other notable changes between what we see in a traditional csproj file when compared to the newer csproj file. Firstly they have gotten rid of the use of GUIDS within the file, so that it is much more human readable. That’s a good change and one I’m happy to see.

We are no longer required to include all of the files within the csproj file in order for them to be considered part of the project. project.json gave us a much more favourable, include by default, behaviour and this has now been made available inside csproj. It’s ever so slightly different as we must use a wildcard style include line to tell the project to behave this way. New projects created inside VS 2017 have this by default. When working with teams of developers, the csproj file was a common area of merge conflicts. We should no longer have so many issues since the project file will not change simply because we’ve added new files to the project.

Package references are now integrated into csproj so this single file also includes any libraries our project is dependent on and any projects we reference. It’s nice to have everything in one place as we’ve become used to with the project.json format.

Another important change is that we can now edit the csproj file whilst the project is loaded. This was not previously possible and meant that any manual changes were slow to make as we had to first unload the project. Granted, it was rare that I wanted to manually edit the file in the full .NET framework days. To edit the csproj file we can simply right click on the project without unloading it first.

Edit csproj inside VS 2017

One gripe at this point that I experienced is a warning for inconsistent line endings every time I edit the csproj file.

Inconsistent line endings

Other project differences in VS 2017

As well as the direct differences inside the file, there’s a few initial tooling differences I wanted to highlight between VS 2015 and VS 2017 that I’ve noticed.

The main one I’ve seen so far is the consolidated dependencies folder. Before, we had a “References” folder which included any dependent libraries we added via Nuget and any project references. We then had a “Dependencies” folder which included Bower dependencies. Inside Visual Studio 2017 these have been placed together inside a single “Dependencies” container. Project references have their own sub-container to separate them from the Nuget dependencies.



Initial Impressions

I definitely don’t find the XML as readable as the JSON for reviewing the configuration of my project. This will improve with time as I get used to it, but there’s still too much noise in the file for my liking. It’s certainly a big improvement on the traditional csproj format though and the wildcard include of files is an important enhancement.

Personally, I still much prefer the project.json format and whilst I understand the business case the led Microsoft to their change of course, I feel it’s a shame the MSBuild system couldn’t have moved with the times, rather than dropping back to the xml based project file.

The lack of autocomplete for dependencies bothers me too. This was really handy and I could quickly build up my dependencies without having to open up the Nuget package manager each time. It feels like we’re now being forced down that route which proves to be a bit slower and less efficient.

It’s still very early days and I need to spend more time with the new version of csproj in a final stable version of VS 2017 before passing a final judgement. We also have to remember that the .NET SDK tooling is not quite fully baked yet either. At this early point I’m running into quite a few issues running VS 2017 so it’s hard to fully appreciate the final experience.

The Microsoft statements suggest that in reality the tooling and command line interface should negate the need to spend much, if any, time editing the csproj manually. Once everything is complete we will be in a better place to judge for ourselves. I can’t help but assume things will end up being slower overall and that I’ll end up missing the ease of the project.json file.

Update 23rd Nov 2016

After reviewing https://blogs.msdn.microsoft.com/dotnet/2016/10/19/net-core-tooling-in-visual-studio-15/ I can see that the format for the new csproj that I have experienced in VS 2017 RC doesn’t match the example of what I presume is the end goal. So it’s entirely possible that the structure will evolve even more before release. The example in the MSDN blog does look cleaner and much less cluttered so I will watch this space with interest.

Update 7th March 2017

Further reflection on the changes and the way it has been handled in my post – Visual Studio 2017 is Released – Reflecting on the loss of project.json and looking ahead to the new VS 2017 experience

31 thoughts on “R.I.P project.json – Out with the new, in with the old An early look at the VS 2017 csproj changes

  1. Hi, Steve!
    I think you’re missing the fact that csproj, being MSBuild scripts, are extensible. Meaning, you can easily add new tasks to it, even your own. You couldn’t do this with project.json.
    Apart from that, I feel the same as you! 😉

    1. If there is so “very cool MSBuild tasks libraries” and if MSBuild is so extensible, why there was not an extension to MSBuild to recognize and compile project.json?

    1. I think it is already build-in in VS as project’s Properties (right click on project in Solution Explorer > Properties). It is the way you can change .csproj in previous .Net versions (tasks, target framework, etc.).

  2. This is an excellent article! Thank you for sharing your thoughts. FWIW, there is an issue on MSBuild’s repo (full disclosure, started by me 🙂 ) that asks for an improvement to MSBuild’s modeling so that it is POCO-based. This means build files are simply serialized POCOs, making it much more tooling-friendly. Additionally (and more importantly), this will allow you to describe those POCOs in any supported format, so either XML *or* JSON (or INI if you can find the serializer to do it!).

    You can find the issue here:

    Thank you for any consideration and/or support. 🙂

  3. I’ve never been a fan on csproj ever since I migrated to .NET from PHP. This was simply for work purposes and in my spare time I still use PHP. I originally loved the concept that I could open a text editor and have a project.json (similar to how in PHP I would have a composer.json file). But csproj is so hard to read that you really do have to have Visual Studio to use it.

  4. Good article. Admittedly we didn’t spend long investigating but how would you reference different frameworks using the new csproj?

    We’ve found VS2017 completely unusable and rushed through to RTM for Microsoft Connect event and have uninstalled it as it was causing an issue with vs2015.

    1. Yes, VS 2017 RC is not working well for me and I’ll have to uninstall it to see if I can get the VS 2015 working normally again. I can’t package restore projects in VS 2015 any longer, I have to dotnet restore from the command line since installing VS 2017 and .Net Core 1.1. Not sure yet which is the cause.

      1. Update your global json for your VS2015 project\solution to

        “projects”: [
        “sdk”: {
        “version”: “1.0.0-preview2-003121”

        1. Actually what I did was place the global json in the root of my project library structure \dotnet\global.json then my libs are \dotnet\libname\dotnetlib.dll etc. So when a dotnet restore is executed it will dig and find the global.json to determine the runtime version.

  5. Good riddance. Can’t stand JSON or any of the other stuff that the ASP.NET team has done that completely ignores what is/was in the full .NET Framework. Maybe the ASP.NET people should have looked at was already there before reinventing the wheel and causing a lot of problems for people.

    1. I totally agree!! We have been using csproj for years. If you don’t get it go back to sh in Unix!

      Seriously, I’d rather have ONE standard for this than two. And no fighting please girls!

  6. It would have made sense if the team would have supported project.json for .net core projects and behind the scenes it updated .csproj as in classic .net, so that way we could continue life as usual for .netcore developing and this would allow anyone to extend on MSBuild. I mean is this too simple of a concept am I overlooking something it would seem that would have been a nobrainer, but editing the csproj even through VS with intellisense using XML is counter intuitive that was the reason for JSON in the first place..

  7. Just tried VS2017 and I really don’t like it. Nuget packages get mixed and I don’t like that. There is not filter to only retrieve dotnet core packages which is very important for cross platform development.

    It would have been much nicer if MSBuild would be able to transform the project.json to csproj file type during compilation. That developers would had a choice between the old csproj files and the instantly loved project.json files. For 5 minutes I was very happy that the Mongo DB driver was ported to dotnet core. But once deployed on my linux box, things stopped working. This ruined my whole VS2017 experience and I doubt Microsoft will be able to wash away that bad taste. First impression count!

    From the first dotnet core release project.json autocompletion was there. After 10(!) years of csproj development, we’re still don’t have autocompletion. We only have tag autocompletion, but not content auto completion. It’s just plain stupid.

  8. Hi, thanks for the post.
    Do you have any idea how development in Visual Studio Code is going to evolve if project.json will be retired?

    1. Hi Petr. I’m afraid I don’t know what plans Microsoft have for tooling VS code for the return to csproj. I haven’t looked into it personally.

  9. All this change makes me scared. I’m currently installing 2017 RC because I cannot use msbuild to build a netstandard project with contentFiles. But the comment about 2017 RC messing with 2015 worries me greatly. 🙁

  10. This is sad news for me. For whatever reason, I have had much greater luck dealing with project.json than msbuild. I’m learning .NET Core and I noticed that suddenly even a hello world apps were broken if I tried to run with VS Code but ran just fine with dotnet run. I have had mysterious problems with upgrading Visual Studio before that ultimately were differences in the configuration file changes that simply weren’t obvious from error and warning messages. The changes are too fast, not well documented to the unpracticed .NET developer like myself, and buggy. Now I have to keep up to date on all the latest changes to configuration files if I want to run a hello world app in VS Code. That’s ridiculous.

    Thanks you for the article. I was frustrated with the changes and now I have an idea of what to expect and how my time was stolen before.

  11. I completely second William – ideally we would have kept project.json for happy-flow ASP.NET Core users and introduced csproj support for our hard-code msbuild folks. Additionally, one could envision a mechanism where an external msbuild file would work on top of project.json. What were the reasons for not following this path?

  12. The fact that we are moving back to csproj over project.json is terrible. We finally got a normal project structure thats easily adaptable to multiple editors and human readable only to get it pulled up from underneath us. I am sick of the VS team constantly standing up at conferences and making excuses as to why they haven’t switched csproj files over to something like project.json.

  13. Hi Steve,
    I have a question regarding the returning feature “add as link”, which was not available in the xproj days. Now it’s back but…. since the new csproj is projects-directory-based (no included file list inside), If i add a linked file I can no longer copy it to the project’s folder. Let me explain. This is for non cs files: I have several shared TS files, config files (webpack, bundle), etc, which i need to be SHARED but also present in the project. If the files are not phisically copied, they wont be really considered by visual studio, just “shown”. An example is webpack.config. It wont show up in the task runner explorer unless the file is really in the directory. Just linking it won’t do it. So, if I add a and “Copy SourceFiles….” instruction in csproj, I copy these files on build. But next time I open the solution it wont load the project stating that some linked files are already there…!
    I have been using the weirdes workaround for this since xproj and now…. cs proj is back but this no longer works… any ideas?

    1. Hi Mauro.

      For your particular query, I’m afraid I’m not sure. It’s not something I did in the prior csproj versions either. I would suggest you reach out to Microsoft via GitHub to see if they can provide any guidance.


  14. Release candidate doesn’t sound like the time to do this type of thing. At some point it should have a feature freeze and only bugfixes until RTM. I hope the tooling becomes more stable with RTM release. Also the announcement only supporting VS2017+ that came along with the project file change doesn’t sound good either. Certainly harms developer confidence if it has no other side effects.

  15. This is why quitting .NET technology as project back-end would be excellent idea. Cause knowing that you have no idea to know what microsoft is going to do with, is great mystery. And this is a disaster for project leader or programmer Specially if you are developing an extensive project….

    1. Jora – Sorry to hear this is putting you off .NET completely. It is a real shame how this came about and I think in some cases could have been handled a bit differently to avoid alienating the earlier adopters. However, I urge you to not give up on .NET over this alone. Overall I’m a fan of the technology and the ASP.NET stack in particular. While the communication and change of direct here was certainly frustrating, overall the development in the open is allowing the community to be involved, see what’s happening and even make contributions to the future of this platform. – Steve

  16. First of all excellent article. Thanks for sharing your thoughts Steve. I certainty agree with Jora, it is really frustrating when Microsoft changes core ideas very often. Especially, I don’t like really going back an idea of .csproj and removing project.json with mystery. Now you left with two options for creating core projects, one type with VS 2015 and latest type with 2017. You have to choose 2017 if your CI machine does not wants to install Visual Studio for building. Because dotnet CLI commands works perfectly with, only projects created by 2017 without installing Visual Studio and this enables truly cross platform. For, VS 2015 still you have to install VS 2015 on your CI machine. This is not certainly interesting one.

Leave a Reply

Your email address will not be published. Required fields are marked *