Missing Edit Project Context Menu in Visual Studio 2017

I was spending some more time this weekend with the updated version of the .NET Core CLI, specifically looking into the sln command which provides a way to manage a *.sln file from the command prompt.

I used the following sequence of commands to flesh out a project on the command-line:

md MyProject && cd MyProject  
dotnet new sln  
md src && cd src  
md MyLibrary && cd MyLibrary  
dotnet new classlib  
dotnet sln ..\..\MyProject.sln add MyLibrary.csproj  

The end result is a project structure that looks something like this:

\MyProject
    MyProject.sln
    \src
        \MyLibrary
            MyLibrary.csproj

Strictly speaking I don't need to create a solution file, or add the project to it but I wanted to have a solution file to make it easier to work across projects using Visual Studio 2017.

One of the nice editions added in Visual Studio 2017 is the ability to right-click on any project in Solution Explorer and edit the underlying MSBuild (*.csproj) file. Unfortunately after opening the solution file I found that this option was missing.

Picture of context menu without the Edit options

Prior to Visual Studio 2017 you could always opt to Unload Project and then edit the *.csproj file, and that still worked, but I had grown accustomed to the new experience so I wondered what was going on.

Curious I brought up the properties for the project to try and figure out what was going on and noticed that the usual property pages experience for .NET code was not being used and instead got a kind of fallback experience.

Picture of modal property page, similar to the C++ property pages

As an experiment created a new class library (MyOtherLibrary), but instead of doing it with dotnet.exe I did it via the VS2017 shell. To my surprise, this approach resulted in the Edit menu being available for that particular project.

Picture of context menu with Edit option

After seeing this I remembered something curious about what data is stored in solution files, vs what is stored in project files. A solution file is an index of all the projects in the solution, along with solution configuration details, hierarchical structure details - but in addition it also specifies the type of project that is being referenced by the solution - this isn't something that the project contains itself.

To investigate further I opened up the *.sln file - this is what the top of the file looks like (open it in Visual Studio Code because Notepad doesn't handle the line endings correctly).

Microsoft Visual Studio Solution File, Format Version 12.00  
# Visual Studio 15
VisualStudioVersion = 15.0.26214.1  
MinimumVisualStudioVersion = 15.0.26124.0  
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{811EC90D-4AA0-4FA6-B609-4B0B16CF743D}"  
EndProject  
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "MyLibrary", "src\MyLibrary\MyLibrary.csproj", "{9EC5196D-1859-49C0-A92F-AE8CADD43AF3}"  
EndProject  
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyOtherLibrary", "src\MyOtherLibrary\MyOtherLibrary.csproj", "{39C59C5E-07AC-4341-8948-10289049C20A}"  
EndProject  

Notice the structure of the lines beginning with Project(. This particular solution file has three Projects referenced. Two of them should be obvious, but the first one is just the src folder which is treated like a project in Solution Explorer. On each Project line there are two GUIDs. The first GUID is the project type, and the second GUID uniquely identifies each project within the solution.

To tell Visual Studio to load the *.csproj file created via the dotnet.exe command-line you just need to copy the GUID from the last project to the second project - in other words, replace {13B669BE-BB05-4DDF-9536-439F39A36129} with {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}. Once this is done you can re-open the *.sln file in Visual Studio 2017 and the menu Edit menu, and usual property pages will be back where they belong.

The good news is that there is already issue tracking this in the GitHub repository for the .NET Core CLI (see issue #5131).

Hopefully this helps someone who is confused as I was when I came across this issue.