About Hasmukh patel

My Photo
Harrow, London, United Kingdom
Dot-Net developer with expertise in Web, WPF, Win-form applications. Have worked on Asp.net,mvc , WPF and Win-forms projects in c#.net language having Sql-Server/Oracle as database with service oriented architecture using test driven development. Having complete knowledge of SDLC and have successfully worked and implemented it on projects.

Upgrading an existing .NET project files to the lean new CSPROJ format from .NET VS 2017 - Part 2

Conver old csproj to new VS 2017 csproj manually 

Disclaimer: this only works for a small set of project types.
  • class library projects
  • console apps
  • ASP.NET Core web apps
  • .NET Core
If you are building ASP.NET 4 (i.e not ASP.NET Core), WPF, Universal Windows, or Xamarin projects, you’ll have to stick with the old format (for now… follow https://github.com/dotnet/sdk/issues/491 and https://github.com/dotnet/project-system/issues/2670 for updates).

Replace the contents of your csproj with the following, based on your project type:

Class library

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net46</TargetFramework>
  </PropertyGroup>
</Project>

Console app

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net46</TargetFramework>
  </PropertyGroup>
</Project>

Test project

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net46</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
    <PackageReference Include="xunit" Version="2.2.0" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
  </ItemGroup>
</Project>

Approach two: manually convert

Trim the fat manually.
Unfortunately, there is no magic button or command line tool to upgrade from VS 2015 to VS 2017 formats.
:warning: Keep your code in source control.

First line

Old
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
New
<Project Sdk="Microsoft.NET.Sdk">

Must delete

These lines must be removed to make the new format work:
<!-- usually at the top of the file -->
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />

<!-- usually at the bottom -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
Test projects usually have one or many blocks named <Choose>. These must be deleted too:
<Choose>
    <When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
      <ItemGroup>
        <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
      </ItemGroup>
    </When>
    <Otherwise />
  </Choose>

Must change

These lines must be changed:
Old:
<PropertyGroup>
  <!-- ... -->
  <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
New:
<PropertyGroup>
  <!-- v4.5.2 => net452. v4.6 => net46, etc.-->
  <TargetFramework>net452</TargetFramework>
</PropertyGroup>

That massive list of files

You can can delete any lines nested in an <ItemGroup> that match with <Compile> or <EmbeddedResource>. This gets special mention, however, because their are excpetions.
By default, the new SDK will pick up default globbing patterns.
<!-- the defaults -->
<Compile Include="**\*.cs" />
<EmbeddedResource Include="**\*.resx" />
If you have anything outside of the project folder, you’ll need to keep those lines so VS and the compiler know where to find your code.

What to keep

These are common, non-default settings:
<PropertyGroup>
  <Optimize>true</Optimize>
  <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
  <OutputType>Exe</OutputType>
<!-- when RootNamespace != the csproj file name -->
<RootNamespace />ClassLibrary1</RootNamespace>
<!-- when AssemblyName != the csproj file name -->
<AssemblyName>ClassLibrary1</AssemblyName>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  <DefineConstants>$(DefineConstants);MY_CUSTOM_CONSTANT</DefineConstants>
  <Platform>x64 or x86</Platform>
</PropertyGroup>

<ItemGroup>
  <!-- keep references unless they are to package files. See the section about the NuGet upgrade below. -->
  <Reference Include="System.Configuration" />
</ItemGroup>

Can remove

:warning: Heads up: these are suggestions for things you don’t need in most cases, but not all.

Project references

Old
<ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj">
  <Project>{2C7DF870-5B35-49EF-963D-EE1E72C3177E}</Project>
  <Name>ClassLibrary1</Name>
</ProjectReference>
New
<ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" />
Also, MSBuild now does transitive project-to-project references automatically.
Example: Project A => Project B => Project C.
Old
Both B and C had to be listed.
<!-- in projectA.csproj -->
<ProjectReference Include="..\ProjectB\ProjectB.csproj">
  <Project>{A900C843-8340-421B-B4F0-6C65A0D093C4}</Project>
  <Name>ProjectB</Name>
</ProjectReference>
<ProjectReference Include="..\ProjectC\ProjectC.csproj">
  <Project>{871AC142-FC46-49F5-A5E0-90436648B9C5}</Project>
  <Name>ProjectB</Name>
</ProjectReference>
New
Only B needs to be listed. Project C will automatically be referenced as long as Project B references it.
<!-- in projectA.csproj -->
<ProjectReference Include="..\ProjectB\ProjectB.csproj" />

PropertyGroup

Bring out the red ink
Now the fun part, start deleting tons of stuff. The following elements under <PropertyGroup> can be deleted.
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace />ClassLibrary1</RootNamespace>
<AssemblyName>ClassLibrary1</AssemblyName>
<Optimize>false</Optimize>
<ProjectGuid>xyz</ProjectGuid>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<FileAlignment>512</FileAlignment>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NuGetPackageImportStamp></NuGetPackageImportStamp>
<TargetFrameworkProfile />
<TestProjectType>UnitTest</TestProjectType>
<IsCodedUITest>False</IsCodedUITest>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
You likely also have duplicates of these properties under a PropertyGroup that looks like this:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
That whole block can usually be deleted too.

NuGet: imports and references

This gets special mention.
Old
In NuGet 2, you had a packages.config file AND you had <Import> and <Reference> items in the csproj file.
<Import Project="..\..\packages\xunit.runner.visualstudio.2.2.0\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\..\packages\xunit.runner.visualstudio.2.2.0\build\net20\xunit.runner.visualstudio.props')" />

<ItemGroup>
  <None Include="packages.config" />

  <Reference Include="MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
  <HintPath>..\..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll</HintPath>
  <Private>True</Private>
</Reference>
</ItemGroup>
New
Delete the packages.config file. Delete any <Reference> and <Import> items that refer to files from packages.
Replace them with <PackageReference>.
<ItemGroup>
  <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
  <PackageReference Include="MySql.Data" Version="6.9.9" />
</ItemGroup>
About transitive references
In NuGet 2, you listed every single package to be included. In NuGet 4 (VS 2017), you only need to list top-level dependencies. Everything else is that those top-level dependencies require will be imported automatically.
Old
<?xml version="1.0" encoding="utf-8"?>
<!-- in packages.config -->
<packages>
  <package id="xunit" version="2.2.0" targetFramework="net452" />
  <package id="xunit.abstractions" version="2.0.1" targetFramework="net452" />
  <package id="xunit.assert" version="2.2.0" targetFramework="net452" />
  <package id="xunit.core" version="2.2.0" targetFramework="net452" />
  <package id="xunit.extensibility.core" version="2.2.0" targetFramework="net452" />
  <package id="xunit.extensibility.execution" version="2.2.0" targetFramework="net452" />
  <package id="xunit.runner.visualstudio" version="2.2.0" targetFramework="net452" developmentDependency="true" />
</packages>
:warning: Figuring this out will be trial and error. Best wishes if you have a long list.
New
<!-- in csproj -->
<ItemGroup>
  <PackageReference Include="xunit" Version="2.2.0" />
  <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
  <!-- Notice that xunit.assert, xunit.core, etc. are imported automatically.-->
</ItemGroup>