I have previously written about What is this Directory.Build.props file all about? and it seems many folks really appreciated the post and it has been tagged and linked in may blog posts since. I really appreciate all the good vibes and compliments regarding it, there are absolutely too many to link back too, but y'all know who you are and thanks!
It was during a bit of a refactoring of my API Template Pack project, that I wanted to centralise all the package versions to a central location, that I started to use the
Directory.Packages.props that I realised that this file is also somewhat under documented so I thought I may as well try detail that for others too.
What is centralised package management
In all likelihood the first question to answer with the Directory.Packages.props file is, what exactly is centralised package management and then why is it important?
Essentially what Central Package Management does is enable you to manage all the Nuget dependencies of your Solution in one file. This is especially useful if you are working on any medium to large scale solution that includes a number of projects, because the
Directory.Packages.props enables you to set the version number of the dependency for package in one place therefore all projects within the solution will make use of that particular version, and if you need to increment or update the version number of the package you only have to do so in one place resulting in all projects in the solution to be update to the new version.
Why is centralised package management important
When developing any medium to large scale project, invariably requires you solution to include a number of smaller projects to break down specific functionality, services, libraries into isolated business or functional concerns with all these libraries requiring dependencies to similar libraries etc.
When creating new class libraries or projects with dotnet the default is that the
.csproj will contain all the Metadata and package dependencies for the class library. This works well for small projects, however over time as the complexity and functionality of your application grows, you'll tend to find that all your project may have slightly different versions of specific libraries referenced, resulting in obscure bugs or unexplained differences happening, because the different versions of packages may behave slightly differently.
This often leads to maintenance headaches, because although the tooling in IDE's have improved over time, they are still not quite 100% resulting in sometimes a reference being missed or even issues with updating certain versions of packages in different projects becoming painful and completely inconsistent.
Directory.Packages.props is a handy mechanism to manage NuGet packages in .NET solutions. It's a single centralised file that is used to manage all the NuGet package versions in a solution and is shared across the .NET projects.
Managing dependencies for multi-project solutions can prove to be difficult as they start to scale in size and complexity. In situations where you manage common dependencies for many different projects, you can leverage NuGet's central package management features to do all of this from the ease of a single location.
How does the Directory.Packages.props file work
One of the great things if if you're already using the Directory.Build.props file in your solutions then its really easy to get set up with the
Directory.Packages.props file in your projects too. At its most basic level the
Directory.Packages.props is just another text file (it is an XML really) at the root of your application. The only rule is that there should be only 1
Directory.Packages.props file for any given project.
What this means is that if you had multiple
Directory.Packages.props files in your repository, the file that is closest to your project's directory will be evaluated for it. This allows you extra control at various levels of your repository.
Once you have created your file then you can add the following content
<Project> <PropertyGroup> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> </PropertyGroup> </Project>
ManagePackageVersionsCentrally tag is set to true , this is a MSBuild property. If ever you want to disable the this setting you can set it too false. You can also set this project on by a project by project solution, if this works better for you.
Once we have this set up we can start define a Package Version that we would want to use, so for instance lets assume we want to make use of the Threenine.Data and we want to ensure the same version of the library is used throughout the Solution we can add the Package and version number of our
<Project> <PropertyGroup> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> </PropertyGroup> <ItemGroup> <PackageVersion Include="Threenine.Data" Version="5.0.1" /> </ItemGroup> </Project>
We can then update our Directory.Build.props files to reference this version
<Project> <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))"/> <PropertyGroup> <RootNamespace>placeHolder.Database</RootNamespace> </PropertyGroup> <ItemGroup> <PackageReference Include="Threenine.Data"/> </ItemGroup> </Project>
Directory.Packages.props file allows you to set a version number once for a NuGet dependency. .NET projects downstream can include the dependency, but will not specify a version number. The project(s) will use the version specified in the