I'm sure most prople must have been frustrated in the past when they go to build a solution, only to get many (maybe hundreds!) of errors moaning that different projects in the solution are using different versions of Nuget packages (I'm looking at you Newtonsoft.Json). Or maybe you've got yourself into the dreaded diamond dependancy situation somehow and your IDE is refusing to help you out!

The Solution

Directory.build.targets to the rescue! The docs on this are here so go check them out for a much more thorough explanation, but in essence, this file lets you manage all the version of all of your Nuget packages, in all of your projects in one place. For example, say you have a solution with 2 projects with the following .csproj files.

Note: Visual Studio does not support managing this file yet, so all packages have to be managed by manually changing the versions in the Directory.build.targets file. For the advantages that this brings I don't mind this, but it's worth mentioning. I'm sure VS and other IDEs will support this in the future.

Project 1

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="MailKit" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
  </ItemGroup>
</Project>

Project 2

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
	<PackageReference Include="MailKit" Version="2.0.0" />
    <PackageReference Include="FakeItEasy" Version="3.3.2" />
  </ItemGroup>
</Project>

As you can see, the MailKit package is used in both projects.

Using the Directory.build.targets file we would change our project files to the below and only look for the versions of the packages in one file.

Project 1

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="MailKit" />
    <PackageReference Include="Microsoft.AspNetCore" />
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" />
  </ItemGroup>
</Project>

Project 2

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
	<PackageReference Include="MailKit" />
    <PackageReference Include="FakeItEasy" />
  </ItemGroup>
</Project>

As you can see in the above 2 projects, I have omitted the Version of the packages.

Next, you need to create a file called 'Directory.build.targets' at the same level as the solution and then all projects will share the same version of Nuget packages like so.

Directory.build.targets file

<Project>
  <ItemGroup>
    <PackageReference Update="MailKit" Version="2.0.0" />
    <PackageReference Update="Microsoft.AspNetCore" Version="2.0.0" />
    <PackageReference Update="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    <PackageReference Update="FakeItEasy" Version="3.3.2" />
  </ItemGroup>
</Project>

And there you go, clean your solution and then build and your solution should build successfully using one file to manage all of your Nuget package version.