Is there a smart way to deal with package dependencies in NuGet? - c#

We are developing a WPF application at work which has various "common" dependencies (Unity, Prism, etc.).
It's all fine when adding new projects and then setting up the NuGet package dependency per project but when it comes to upgrades, it's really painful as it means we have to go through each and every project, delete the old references and then refetch the latest packages from NuGet.
Today for instance, I was tasked with upgrading Prism from 5.0 to 6.0 (which has breaking changes anyway) and this meant, in addition to fixing all the namespace conflicts, etc. that I had to go through every project, delete the old references, add the new dependecies and rinse and repeat.
My question is, is there a smarter way to deal with this problem or is this the standard approach?
Many thanks in advance,
Update:
I am mostly concerned with "major" upgrades which don't show up on the package manager. Version 5.0 -> 6.0 upgrade would be treated as a major upgrade and hence, would not have an automatic update applied to it in the NuGet package manager.
I don't expect NuGet to be able to do this automatically for me since such upgrades may (and often do) include breaking changes but I would like to know if there's a way to do the major upgrades less painfully than deleting the references from the projects and the packages.config for every project and then re-adding them using NuGet. For a relatively large project, this is very time consuming and I was wondering if anyone had a better way of managing such dependencies.

If you use VS2013 like you say, you can manage ALL your NuGet packages by right-clicking on your Solution and selecting 'Manage NuGet Packages For Solution'. This brings up a dialog where you can view all packages installed for all projects in the solution and all packages that have updates available. When you do upgrade the packages, VS takes care of all the reference changes required. If the package has breaking changes, then you're still on the hook for fixing those.
Disclaimer: I've never worked on a WPF project/solution but for Web/Forms apps, NuGet packages are handled this way.

I can understand your pain because i had the similar problem like you, but there is no easy way. but certainly you need to break the process differently of your daily development and your dependency update roll-out.
for the project i worked on, I use the common repository path that shared among the solutions that you work on, and you need to delete all the solutions folder references in order to get a clean state.
For each solution you work on you need to modify the property group that point to the common target repository (i'm using relative path)
Once all the things setup, you can actually perform an update with a script(I'm using python run-time script)
you can actually look at setting up common nuget-packages-folder for reference updates for detail, but it seems like what you looking at for the automate process

I had a similar problem when trying to upgrade multiple packages with alpha channel issues in Xamarin Studio, which also does not have the niceties of VS 2015 NuGet manager. I ended up writing a very simple PowerShell script that I run multiple times a day.
#
# This script updates local ibGib NuGet packages for mobileGib Android app solution.
# For convenience in copy+paste in manager console:
# ../UpdateLocalNugetPackages.ps1
Update-Package commonGib
Update-Package ibGib
Update-Package languageGib.Biz
Etc.
I believe you could tailor your NuGet commands to fit your needs.
Also, just in case you aren't aware of it, you should definitely read the NuGet command line reference. I may be mistaken, but it sounds like your scenario is doable with the Update command.

Related

How to handle NuGet dependency version resolution for the whole solution

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.

Automatically Propagating Changes from Parent to Dependent custom NuGet packages using TeamCity

My company uses the built in TeamCity NuGet repo to create custom NuGet packages that often depend on each other. When I, say, update a .cs page in a custom parent package I'd like for those changes to propagate to all of our packages that are dependent packages of the parent - I believe I can accomplish this using a NuGet installer to "update packages".
My fear is that while I know I can force this update upon all our packages, I want to find a way to exclude anything that isn't hosted on our company repo (which should also mean anything that is hosted on the NuGet.org repo), so anything that we are using from an outside source isn't lumped into this NuGet update.
Preferably, I'd like to know if there's a way to handle this in the our .nuspec for each of our packages (though it seems wildcards don't accomplish this). Any insight to my problem here?
Honestly, it sounds a bit like you're trying to re-create the project reference experience with NuGet packages. If it's at all reasonable to do so, perhaps your best option would be to have all projects in a single solution and use project references instead.
If you're able to migrate your projects to SDK style projects (used by .NET Core, but you can still target the .NET Framework), then you can use dotnet list package or the dotnet-outdated tool. dotnet list package --outdated has an option to specify a list of sources to use. Perhaps if you only specify your private feed it may only search that one. Otherwise the script you create to do all this will need to overwrite the nuget.config file to remove other sources (like nuget.org) when running the command to get your desired output. Then you parse the output and when it finds an update, it modifies the relevant file(s).

Versioning Issue With Local NuGet Server Packages

Some background:
At my company, I have been working the last few months with converting our C# libraries to function on .dll references instead of project to project references. To do this, we have created a local NuGet server which contains NuGet packages for all of our libraries projects. We have Jenkins jobs set up for every project which build new NuGet packages and add them to the server every time a change is made to one of them.
For working on a single project, this system works great. You only have to worry about updating your packages folder through Visual Studio's NuGet manager, and then the rest is just writing code and building.
The issue:
When you add a new reference, or update your packages through NuGet, NuGet automatically specifies that specific version of the project that you selected in NuGet. With the current system I have setup, rebuilding a project locally will then replace it's .dll in the packages folder so that all projects that reference it can see these new changes you're testing. However, the issue come in that locally built projects have a different version than our Jenkins built packages. Our local builds use a different versioning system from our Jenkins builds so that you can easily tell whether something was built using Jenkins, or if some of the .dlls came from a developer's build. Because of this different versioning scheme, the reference of projects to the project breaks, because the new .dll that was built locally has a different version than the .dll that was retrieved from the NuGet server.
Current Solution:
For the moment, I have resolved this through the addition of a pre-build step. Before every project builds, the project calls one of my PowerShell scripts, which goes through and adds <SpecificVersion>False</SpecificVersion> to every project reference in the project being built's .csproj file. This resolves the issue, but only in the sense of putting a bandaid on it. Instead of dealing with the consequences of the system, I wanted to prevent them ahead of time so that this isn't needed every time a project builds. I have tried researching a lot about NuGet packages specific versioning issues, but have not been able to find anything online even remotely close to what I am asking. This makes me think that I'm going about this wrong.
The question:
What can I do to solve this issue? Or am I doing something very wrong and dumb that could be easily avoided by using another system? Any suggestions or tips would be greatly appreciated

Adding reference of another external project in a solution

Using: .net core mvc c#
I have a solution which has a .net mvc core web app & one class library. There is a shared project (class library) that I want to this solution
which is a part of different project (different solution as well).
All of these projects are stored in our local GIT repository.
If I add the external project as project dependency in my existing project then there would be 2 copies of the external project that we have to
maintain. If some developer updates external project how does the change propogates to other projects using it.
And there could be that some developer updates the external project when under its local solution which we want to prevent. Since all are in GIT
is it possible somehow to make dependency related so that any change in external is known to others.
So basically how can we prevent anyone to make local updates to the external project but also make sure any updates to external project are available to
any other project using them.
There are several approaches that you can use to achieve this.
Quick: Reference project in two solutions
The quickest is to reference the shared project from both solutions. This way, you can use it in both projects and the changes are propagated to the other solution because you are basically working on the same files. However, a huge drawback of this approach is that if you make changes in solution A that are not compatible with solution B (e.g. removing a method that is used in solution B), you will only find out when working on solution B.
Easy: Single solution
To fix this, you could merge the solutions into a single one that contains the shared proect and also the other projects from solutions A & B. This way, you still get the convenience of project references in a solution. In addition, you are notified about breaking changes immediately if you build the complete solution. If this approach is viable for you in terms of solution size and team structure, I'd favor this approach. As you already share a single Git repository, I think this approach is well worth considering.
Nuget Package
If you want to keep the solutions strictly separated, you'd need to follow a more complex procedure. You could for instance move the shared project into a solution of its own and create a Nuget package with a clear build and versioning strategy. You can host the Nuget package on a package feed (e.g. on Visual Studio Team Services). Solutions A and B can then reference the Nuget package from the feed and also update it if a new version becomes available.
Here the official documentation to create nuget package with nuspec or csproj
Create .NET Standard 2.0 packages with Visual Studio 2017 [CSPROJ]
Creating NuGet packages [NUSPEC]

Why is the MathNet.Numerics NuGet package so big?

I recently added MathNet.Numerics through NuGet to my C# solution. The package directory in the solution folder ballooned to about 50 MB! Yet I can simply download the MathNet dll and use only that, which takes up only 1.5 MB. If I want documentation as well, I can include the XML, which is another 3.5 MB.
Am I using Nuget wrong or is this expected behavior? It seems like it is wasting a lot of space.
The reason the package contains that many editions of the same version is a conflict of interests:
We would like to support a wide range of platforms.
We would like to leverage advanced features even if they are only available on some of the platforms (usually only on the full .Net framework, like TPL or System.Numerics), for performance but also for compatibility and usability reasons.
Avoid downstream dependency nightmares by only publishing a single package per version, including all platforms.
If this is causing you problems, consider to bring this point up with the team in discuss.mathdotnet.com (new) or maybe open an issue in GitHub.
PS: If NuGet doesn't work well for you, we also provide Zip archives you can handle manually and pick exactly what you need.
It looks like expected behaviour. It is up to the NuGet package owner to decide how many versions to put in a single package.
You can probably safely delete it, but it'll come back every time you restore the NuGet files. If you are worried about a lot of bloat being included in your build or release, check your .csproj file and make sure you only copy over the MathNet.Numerics.dll version you need.

Categories