P3.NET

Migrating to Package References

One of the better changes in Visual Studio 2017 is the moving of the NuGet packages out of packages.config and into the project file via package references. Unfortunately all the documentation that I’ve seen seems to assume that this is a new project or at least one that was created in Visual Studio 2017. In my experience this is unlikely to be true. This article will discuss the steps I use to migrate an older project to using package references.

Should You

The first thing you need to ask yourself is whether you should or not. While having everything in a single file is nice there are some issues with it. The biggest issue is that packages that are referenced this way no longer run config transformations or can modify files that are inserted. If you rely on packages that require this (i.e. EntityFramework) then you’re out of luck.

Secondly support for package references is currently limited. There are mixed documentation on what project types are supported but the general set appears to be this (as of Aug 2017).

  • .NET Core
  • .NET Standard
  • UWP (Creators Update or higher)
  • Class Library (.NET Framework)
  • Unit Test (.NET Framework)

Updating the Project

The first thing you need to do is ensure you are building using the latest tools. For that you need to edit the project file. You can do so either via  text editor or directly in Visual Studio. I recommend using the Project File Tools extension if you do. Find the root Project element’s ToolsVersion and change it to 15.0. If you’re using the new project file format then this step is not necessary.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="15.0">

Cleaning Up Root Properties

Clean up the root PropertyGroup of any old NuGet properties and add the new properties for the package references.

  • Add a RestoreProjectStyle element with a value of PackageReference.
  • Add an AutoGenerateBindingRedirects element with a  value of true. You don’t need to do this in all cases but I’ve never run into issues with having it in.
  • Add a RuntimeIdentifiers element with a value of win.
  • Remove the RestoreNugetPackages element if it exists.

The runtime identifier is annoying. You shouldn’t need this but because of some code in the NuGet target that is looking for the old project.json file you can get build errors about a missing project.json without this line. It basically says that you’re targeting Windows. For .NET core projects and projects not targeting Windows you’d use another RID.

<RestoreProjectStyle>PackageReference</RestoreProjectStyle>    
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<RuntimeIdentifiers>win</RuntimeIdentifiers>

Adding Package References

Now you need to add each of the NuGet packages you depend on to the project file. You can get the initial list from the packages.config file in the project. Create a new ItemGroup in the project. For each package add a PackageReference element to the group that identifies the package and version being used.

<ItemGroup>
  <PackageReference Include="FluentAssertions" Version="4.5.0" />
</ItemGroup>

One benefit of the new reference syntax is that you only need to include packages you have a direct dependency on. If a package has a dependency on another package then you can leave it off and it will get automatically added. Also ensure that you only include the reference once.

Removing Old References

The binary references that are in the file are no longer needed so scan for the list of Reference elements that point to the packages and remove them. A single package may have multiple references so remove them all.

<ItemGroup>
   <!-- Remove these
  <Reference Include="FluentAssertions, Version=4.5.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
    <HintPath>..\packages\FluentAssertions.4.5.0\lib\net45\FluentAssertions.dll</HintPath>
    <Private>True</Private>
  </Reference>
  <Reference Include="FluentAssertions.Core, Version=4.5.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
    <HintPath>..\packages\FluentAssertions.4.5.0\lib\net45\FluentAssertions.Core.dll</HintPath>
    <Private>True</Private>
  </Reference>
   -->
  <Reference Include="System" />
  <Reference Include="System.Core" />
  <Reference Include="System.Xml" />
  <Reference Include="System.Xml.Linq" />
</ItemGroup>

Update to MSBuild Restore

You need to ensure you are using the MSBuild restore and not the old NuGet/automatic restore that was previously used. Scan the project file and remove any references to the RestoreNuGetPackages element. Also remove any references to the Nuget.targets file.

Finishing Up

The project file changes are done so save and close it. Reload in Visual Studio. Delete the packages.config file from the project. You should now test the build.

  1. Clean the solution.
  2. Close Visual Studio.
  3. Delete the packages folder. You do not need the repository.config either.
  4. Open the solution.
  5. Rebuild.

If everything builds correctly then you are good to go.

Comments