I recently got an email from a friend looking for some help with a NuGet package installation issue. It seems that with the Visual Studio 2015 version of NuGet, the wrong version of dependencies the package author is getting installed. This is related to a policy decision about NuGet to make it’s default behavior more conservative about which versions of packages it would install. In this post, we’ll walk through troubleshooting this package and discuss what the author can do to improve their consumers experience as well as how the package consumer can use NuGet to install the dependency versions they want.
The Problem
For this post, I’m going to change the names of the packages that were referenced in order to make things a little easier to follow and to protect the innocent. My friend was trying to install CoolPackage.ASP from nuget.org which depends on CoolPackage.Base and that package depends on CoolPackageUtilities. The current version of CoolPackage.ASP is v3.0 and it references CoolPackage.Base version 3.0 CoolPackage.Base references CoolPackage.Utilities, which has released versions 1.0 through 3.2.1
With the default options configured in NuGet in Visual Studio 2015, when my friend installed CoolPackage.ASP NuGet acquired and installed the following versions:
CoolPackage.ASP | v3.0 |
CoolPackage.Base | v3.0 |
CoolPackage.Utilities | v1.0 |
Huh? Why did version 1.0 of CoolPackage.Utilities get installed? There is a version 3.2.1 available, why didn’t NuGet install that one?
Investigation
Let’s take a look at the nuspec that is bundled inside of the CoolPackage.Base package to learn more:
<dependencies> <dependency id="CoolPackage.Utilities" /> </dependencies>
Starting with v2.8, NuGet is more conservative by default and will install the lowest version of packages that the package author depends on. In this case, CoolPackage.Base did not specify a version attribute for the CoolPackage.Utilities package. NuGet reverted to its default behavior and located the lowest version of CoolPackage.Utilities package.
Remedies
In general, it’s not a good idea to deliver a package with dependencies that don’t have a version or version range specified. Version ranges in NuGet can be specified using some nifty parenthesis and square bracket notation. If you only specify a single version number, then the NuGet clients will install AT LEAST that version of the dependency.
Additionally, if you as a package consumer would like to make NuGet more aggressive about which versions of dependent packages you would like it to install, you can set an option on the right-side of the user-interface to instruct NuGet to install different versions:
By default, this combobox has ‘Lowest’ selected. If you want to change the default for your project, solution, or even across your entire machine you can add an entry to your NuGet.config file that forces this setting:
<?xml version="1.0" encoding="utf-8"?> <configuration> <config> <add key="dependencyVersion" value="Highest"/> </config> </configuration>
You can save this simple NuGet.config file into your solution, a project, or add this setting to your machine-wide NuGet.config file residing at %AppData%\NuGet More information about the various settings for NuGet.config are available in the online docs.
You can also override the dependencyVersion when installing or updating from Powershell by adding a -dependencyVersion switch with the value you want to use.
Summary
You can configure NuGet to be as conservative or aggressive as you would like in determining which packages to install and maintain in your project. If you want the earliest versions, latest patch versions, or some combination of those you can specify that when you add packages to your project. Package authors can control what versions of packages are recommended to be installed by adding and controlling the ‘version’ attribute of the dependencies in their package’s nuspec files. These choices are up to all of you, and ultimately the package consumer can install and maintain whatever versions they wish.