Over the last year or so at DrDoctor, we have slowly been trying to shift away from old school .NET framework and head towards the new world of .NET core. Initially we thought that the path was going to be relatively smooth – which as always was not the case.
In this series of blog posts I will try and cover the problems our team has faced when attempting to slowly move towards the .NET core world from a relatively large distributed-but-monolithic .NET framework solution.
Transitive dependencies do not get pulled through to a consuming project, resulting in runtime “file not found errors”. For example:
In this example above I have two projects:
- .NET Standard 2.0 class library that has imported the NuGet package “SharpRaven”.
- .NET Framework 4.6.1 console app that consumes the above library, and instantiates a class from said library.
As we can see when I run my console app I receive a runtime error which complains about not being able to find the NuGet package SharpRaven that is referenced by the class library (i.e. a transitive dependency of my console app).
The way in which projects reference NuGet packages has changed for .NET standard and .NET Core (also known as “SDK style” projects). Up until recently we would have a separate file within our project called “packages.config” which automatically gets generated when you add a package to your project (as we can see in my screenshot above).
However the “new and improved” method does away with this separate file and instead includes NuGet references within the .csproj file itself as <PackageReference> tags.
Old Way (packages.config) :
New way (within .csproj):
Any projects that use the “old style” and also reference “new style” projects will not receive the transitive dependencies (that usually get pulled as .dll files into the consuming projects /bin folder.
Luckily, in some cases there is a very simple solution; convert the old style projects to use the “new way” of referencing NuGet packages. Even better – Visual Studio has inbuilt functionality to do so.
First, we right click the packages.config file within our old-style project, and find the “Migrate…” option (as seen below)
Then follow the simple wizard through the steps
All going well, your problem should now be solved. Because both projects are now using the same method of referencing NuGet packages, therefore the transitive dependencies will now be “pulled through” to your consuming projects /bin folder.
As a sidenote – it is also possible to set the default project package management to PackageReference for any new projects within VS. Find the option in Tools => Options => Nuget, as follows:
The Caveats to the Solution
As always things are never this simple. It turns out that there are specific limitations to the new <PackageReference> format, and some of these limitations are big enough to prevent you from converting older-style projects to the new way of doing things.
If you are consuming NuGet packages that either depend on powershell “install.ps1” scripts or packages that use “content” assets – these are both incompatible with the PackageReference format.
In my next post I plan to investigate these issues further and explain possible workarounds in these scenarios.
For teams that are looking to shift their own enterprise solutions to .NET core it usually seems like a sensible first step to start by converting their class library projects one by one to .NET standard.
For our team this seemed like a harmless and relatively simple procedure – however we soon realised that the path from .NET framework to .NET core is not without its bumps and unexpected roadblocks. Hopefully whoever reads this can benefit from our lessons – saving a lot of time and frustration!
I was surprised that I hadn’t seen many warning signs from individual developers or the .NET team themselves about the difficulties of interoperability between the two flavours – but I guess it is still early days..