I'm working on a C# project in Visual Studio 2013 where we develop many nuget packages to be consumed in multiple different applications. We have encountered some nuget.org packages where we want to "pin" to an old version, and have that expression of the old version of the package be centralized.
For example, we are not compatible with Unity 4 or NUnit 3, so we want to stick to the prior releases of those packages.
I don't like using "allowedVersions" in packages.config, because
it's not centralized (every project will have to have this entered)
The GUI in Visual around updating packages at the solution level ignores project level "allowedVersions"
I've played around with expressing the version pinning in a root level nuget package that had a .nuspec with dependency lines like this
<dependency id="Unity" version="(,4.0)" />
<dependency id="NUnit" version="(,3.0)" />
which seems to block all consumers from advancing to an unsupported version. I like this because it's simple and I can just tell my teammates to make sure every package includes that root level nuget package.
The one things I don't like is that every consumer of this root package will get a reference to packages that they don't necessarily use.
For example, my released application will now have a reference to NUnit, despite not using it at all.
Is there a way that I can express version pinning in Nuget without getting these unnecessary dependencies?
Related
When installing the two Nuget packages Hl7.Fhir.DSTU2 and Hl7.Fhir.R4, we get something like this:
The package DSTU2 seems to have issues using Hl7.Fhir.Support.Poco version 3.4.0.
If we install DSTU2 on it's own, all packages are using the version 1.9.0.
Is there a way in the .csproj file to specify sub dependencies versions and have the .dll installed in specific folders?
Here are the 3.4.0 versions .dll in my debug folder
Yes, you just add a PackageReference in your project for the transitive dependency as well. NuGet picks a single version to use for each package you depend on, and if you have a direct reference to a package then NuGet will always pick this version due to its nearest wins rule.
As you've spotted though, this can't be a lower version than any of your dependencies require themselves, or you get a package downgrade error. This is intentional - if you reference packageA which says it needs at least a particular version of packageB, then given that you can only use one version of each package it stands to reason that you need at least that version of packageB.
I'm looking for a simple way to manage NuGet packages for the whole solution, to prevent conflicts between transitive NuGet packages when assembling all files into one installer.
When building a project all direct and indirect dependencies are analyzed and the NuGet resolution picks up the best matching version for each NuGet that is at least the same version as the lowest version and might also create binding redirects if necessary. (all good and fine)
The problem we have lately encountered was when we build the whole solution (200+ projects) at once, the resulting NuGet versions between all top level projects might not be identical. And due to the fact, that all resulting DLL and EXE files are installed into the same program files folder, the application can and will crash at runtime due to version mismatches when loading assemblies.
To better understand this issue I've created this sample repo.
The dependency graph looks like this:
Library1
Microsoft.IdentityModel.Tokens-5.2.1
Executable1
System.IdentityModel.Tokens.Jwt-5.3.0 (transitive reference: Microsoft.IdentityModel.Tokens-5.3.0)
Library1
results in: Microsoft.IdentityModel.Tokens-5.3.0
Executable2
Microsoft.IdentityModel.Tokens-5.2.1
results in: Microsoft.IdentityModel.Tokens-5.2.1
To demonstrate the problem, all projects compile to the same bin folder. When the whole solution is compiled and Executable2 is started, the application crashes, since the application expects Microsoft.IdentityModel.Tokens in version 5.2.1 but the actual version is 5.3.0.
For this constructed sample it is easy to find the problem and fix it with updating the Microsoft.IdentityModel.Tokens NuGet to the same version. (Manually, since Visual Studio Package Manager does not recognize this conflict in the consolidate tab).
But at a much greater scale it is far more complex to find those mismatches.
What we have found so far
Centrally managing NuGet package versions
Since it is not yet available, it cannot be used to solve the issue here.
Microsoft.Build.CentralPackageVersions
Unfortunately there is no IDE support for it, which makes managing NuGet packages very uncomfortable, which I would like to avoid if possible.
So my question is what is the best approach to avoid NuGet version conflicts between projects within the same solution?
We've experienced the same problem with some of our projects. We've been using Paket package manager since a couple of years and this has resolved that issue for us.
In short: you define on your solution level which packages you want to use in a file called 'paket.dependencies'. You can be very specific about versions, or let packet use the latest greatest. Then you can specify per project which NuGet package you want to use within that project in a 'paket.references' file. As the name implies, you reference to a package in the paket.dependencies file.
This will make sure, all references packages in your project will use the same package version. I hope this suits your needs as well.
We have a solution from where we build nuget packages. In addition there is a web application within the same solution that uses project references to include code from these packages. The version number (in AssemblyInfo.cs) is 11.0.0.0. Then we have another solution that uses the nuget packages from the first one. From this second solution we also build nuget packages, where we specify at least version 11.0.0.0 of the nugets from the first solution (in the nuspec-file). And to complicate matters the web application uses these second nuget packages.
Then we arrive at the problem. The nuget packages from the second solution tries to install nuget packages from the first solution when installed for the web application, even if these are added as project references. it seems like the nuget dependency resolution only looks at packages.config, and disregards the referenced DLLs.
Any ideas on how to fix it, so that the nuget installation for the web application doesn't try to install the references projects as nugets?
Our environment: ASP.Net MVC using .Net Framework 4.8. Visual Studio 2019.
Regards,
Bjørn Terje Svennes
So I used to use the old packages.config method of installing nugets which worked by installing any dependencies when installing a package: i.e.
Package 1
Dependency 1
Dependency 2
I have now changed to use PackageReference but noticed as I was installing "Package 1" it would not automatically install the dependencies. As I wasn't sure I went and installed "Depdendency 1" and "Dependency 2" manually
Do I need to manually install "Depndendency 1" and "Dependency 2" when using PackageReference?
The direct answer to your question is simply no, you should not need to manually install the dependencies.
There have been a few changes and performance improvements in the recent VS 2017 and MSBuild work. There's some good information on what this means here:
In the past, if your project referenced package A, which in-turn referenced packages B, C and D, you would see all of them listed as your dependencies. With Transitive Package Restore, NuGet dynamically resolves dependencies giving you an uncluttered view of the packages you care about.
That explains the "missing" package references. If you're interested in the "missing" files themselves, there's more information on that too:
Solution-local packages folders are no longer used – Packages are now resolved against the user’s cache at %userdata%.nuget, rather than a solution specific packages folder. This makes PackageReference perform faster and consume less disk space by using a shared folder of packages on your workstation.
The reason I said should not need to is that there is a known issue around this area when mixing .NET Standard and .NET Framework.
I just switched from (an older) Microsoft.Bcl.Immutable NuGet package to System.Collections.Immutable and was surprised to find all these new package dependencies in my project:
System.Collections
System.Diagnostics.Debug
System.Globalization
System.Linq
System.Resources.ResourceManager
System.Runtime
System.Runtime.Extensions
System.Threading
They are listed as dependencies of the NuGet package, so they have a right to be there, yet they are obviously also already installed on my PC and my target environment (Azure btw) as they come with the framework.
I already have a large number of packages in my project and would like to avoid the additional overhead caused by these 8 packages, if possible (and without shooting myself in the foot).
Is it safe to remove these dependencies?
Do I now have to use these packages throughout my project because they might differ from their installed versions and some portion of my project might now use the wrong ones? (due to some DLL linking madness?)
Edit: Just for completeness, as there was a comment before: The dependencies are actual packages (not namespaces) and have to be downloaded, I'm targeting and compiling with .NET 4.6, working in VS2015. It's entirely possible though that something is outdated and the packages do not have to be loaded normally?
You are just seeing a side-effect of the Nuget package having to keep a lot of people happy. The package supports an enormous number of targets, it is proliferating rapidly as of late. I see support for Xamarin for OSX and iOS, Windows Phone 8.0 and 8.1, Windows Store, CoreCLR (the open source project), .NET 4.5, MonoTouch for iOS and Android and .NETCore (Silverlight).
These dependent packages just contain reference assemblies, the kind that are normally installed in your c:\program files x86\reference assemblies directory. The Nuget package doesn't take the chance that such a reference assembly might be missing and includes the whole kit and kaboodle.
After it is all downloaded, the package installer runs and adds the references you actually need in your project. Easy to see what happened, just open the References node of your project. If your targeted the desktop version of .NET 4.5 and up, the grand total of added references is one, just System.Collections.Immutable. Yes, you can remove them.