.NET
.NET 5/6+ Migration Strategies for Your NuGet Package Libraries
(This article was updated on November 17, 2021, to reflect .NET 6’s release.)
Choosing how—or even whether—to migrate your NuGet package libraries from .NET Framework to .NET 5/6+ depends on each application. Choose between five migration methods: abandon, update, fork, multi-target, or bridge.

Planning the migration of various .NET applications and NuGet libraries to .NET Core “vNext” (.NET 5/6+) is complicated. You likely have many applications and a lot of libraries, all in different lifecycle stages, ranging from ancient to still-being-planned. You can’t migrate your existing applications until you migrate your libraries.
But this presents a problem:
- .NET 5/6+ applications cannot use .NET Framework libraries
- .NET Framework applications cannot use .NET 5/6+ libraries
Therefore, how can you possibly migrate your libraries from .NET Framework to the new .NET?
There are five options for migrating your libraries to target a new .NET platform: abandon, update, fork, multi-target, or bridge.
In this article, we explain what each option entails, when you might want to choose it, and how to execute that option. We start with the simplest option but keep in mind that you must assess your applications, libraries, and migration plans to determine which option is best in each case.
Choice 1: Abandon 
If you have no plan to ever move your library to .NET 5/6+, it will remain a .NET Framework library forever, receiving only small updates over the course of its lifetime.
What | Abandon |
When | Libraries using deprecated technologies |
Pro | No extra/new work |
Con | The library will never be usable in .NET 5/6+ and will be only usable on an unsupported OS once the operating system goes out of support |
How | Continue maintaining the library minimally and only as needed |
When to Choose
“Abandon” is appropriate for a library that makes heavy use of technologies deprecated or not part of .NET 5/6+ (Web Forms, WCF, and WF). There will be many applications and libraries at your organization that use “old” technology, but which will persist indefinitely without needing to be rewritten. Web Forms applications are a great example.
Example
Perhaps you have a library called Kramerica.WCF.Utils that you use only in WCF-based applications. Since WCF will never be part of .NET 5/6+, there is no point in migrating that library. Just maintain Kramerica.WCF.Utils minimally and only as needed.
Choice 2: Update 
“Updating” your libraries means migrating from .NET Framework to .NET 5/6+ while keeping some “room” in the version numbers for emergency releases.
What | Update |
When | Most applications will use .NET 5/6+ but some old applications using .NET Framework endure |
Pro | Leaves room to “fork after the fact” in emergencies (i.e., you can roll back to an older version) |
Con | Must maintain the original library until the new one is released |
How | Leave room between the .NET Framework library’s last version number and the first .NET 5/6+ version number |
When to Choose
If you’re going to be migrating ALL your applications in a short amount of time, it’s fine to update your old libraries and migrate to the new all at once. This option is also appropriate for libraries only being consumed by a very small number of applications.
How to Execute
Libraries are versioned. When you retarget, fix the code errors, and publish the “new” library, use a significantly higher major version number.
Using a big version bump (for example, Kramerica.Utils 2.6 up to Kramerica.Utils 5.0) communicates to consumers that there is a significant difference between the libraries. But perhaps more importantly, it provides enough versions between old and new to allow rollbacks. In an emergency situation, you can essentially go “back in time” and create a new version of an old library—essentially, you “fork after the fact.”
Example
Kramerica.MVC.Utils uses MVC technology, which can be migrated to 5/6+. This library could be updated with minimal changes when migrated. When migrating, you version the “old” library Kramerica.MVC.Utils 3.1, and you version the “new” to Kramerica.MVC.Utils 5.0.
Choice 3: Fork
Like choosing File > Save As on a Microsoft Word document before making changes, “forking” copies all the same source code into a separate repository. After copying, you can migrate in your libraries, target the new .NET platform, and you’ve got a whole new library without altering or removing the old one.
What | Fork |
When | Framework and 5/6+ applications that will coexist in the mid-to-long-term |
Pro | The new library and old library start the same but then continue independent of each other |
Con | Multiple, sometimes very similar codebases to maintain, release, and keep “in sync” |
How | Copy the library, retarget, fix the code errors, and publish with a new name |
When to Choose
If you’re going to need the .NET Framework version of your library for the mid-to-long term, you should fork. You may also consider this option if the migration will be complicated (as when parts of the .NET Framework in your library don’t exist in .NET 5/6+).
A guideline for forking is where 80-90% of the code will “overlap” but 10-20% are sufficiently different, it makes sense to fork. When this ratio is reversed or when the migration is trivial, forking will leave you with two, nearly identical codebases to maintain and release separately.
How to Execute
This is a relatively short, four-step process:
- Fork the current library.
• Copy the source code and rename the project/repository similarly, such as Utils to UtilsCore. - In the fork, change what Visual Studio will target.
• If you tried to compile after this step, you would almost certainly get errors. - Fix errors created by the retargeting and test.
• Repeat this step until you are error-free. - Publish the library with its new name.
Example
Kramerica.Network.Utils is forked to create Kramerica.NetworkCore.Utils.
Choice 4: Multi-target
Creating a single NuGet package library that contains both versions of your libraries (the .NET Framework version and the .NET 5/6+ version). This is very efficient because Visual Studio decides which .NET platform to target.
What | Multi-target |
When | Efficiently supporting multiple applications on different .NET platforms and keeping libraries in sync |
Pro | One library is usable in both .NET Framework and .NET 5/6+ |
Con | Multi-targeted code is complicated to write and maintain |
How | Create one NuGet package with both (or more) libraries inside it |
Consider movies as an analogy: If you buy the original Star Wars trilogy in hard copy, you’ll find a set of DVDs and Blu-ray discs in the same package, so you can play the film on whichever player you have at home. You have both choices at the same time, just like a multi-targeted NuGet package. (A note, though: while most Blu-ray players can now play DVDs, we have no evidence from Microsoft that .NET 5/6+ will ever be able to use Framework libraries.)
When to Choose
Creating a new application, you tell Visual Studio what .NET platform you’re targeting. If you’ve created a multi-targeted NuGet library, Visual Studio can select the right library from the different choices each time it compiles, saving you time.
Choose multi-targeting in situations where the .NET Framework library and the .NET 5/6+ library will be substantially similar, even if the “newer” library has different or additional functionality. (Blu-rays can do more than DVDs, but it’s still the same movie!) This is a great option if the codebase will remain mostly the same.
Be careful, though. There is a lot of information out there about multi-targeting, so it can be very hard to know whether you’re getting helpful advice.
How to Execute
When you compile C# code, you can pick what type of assembly you want, such as .NET Framework or .NET 5/6+. A NuGet package (zip file) has libraries under a subfolder named after the type of assembly. In this way, a NuGet package can have both a .NET Framework library (under the .net452 folder to specify version 4.5.2), or a .NET 5/6+ library (under the net5.0 folder).
The general concept of getting this to work is twofold:
- Configure your project to compile/build multiple times: once for each platform, you want to target (for example, .NET Framework 4.5.2 and .NET 5.0).
- Build a NuGet package out of all of those assemblies.
For detailed instructions, consult the documentation for Windows use or for Visual Studio for Mac.
Example
Kramerica.Data.Models go from being a NuGet package that contains only a single Framework 4.8-compatible library to a package that contains multiple libraries, Kramerica.Data.FrameworkModels and Kramerica.Data.CoreModels.
Choice 5: Bridge 
If you’re lucky and your library’s code just happens to be compatible with a now-deprecated technology called NET Standard 2.0, then you may be able to create a library that works in both .NET Framework and .NET 5/6+ without the complexity of multi-targeting.
What | Bridge |
When | Buy time before making another choice (only if your code supports it) |
Pro | One library is usable in both .NET Framework and .NET 5/6+ |
Con | Adopting a deprecated technology that will keep the library “locked” to .NET Framework’s functionality |
How | Changing your library’s targeting to .NET Standard 2.0 |
.NET Standard was a predecessor to .NET Core and was Microsoft’s attempt to unify all the .NET platforms prior to .NET 5/6+. It’s a confusing technology, but the bottom line is that it may be a good choice if your libraries are already targeting.NET Framework 4.7.2 or later.
Continuing the Star Wars DVDs and Blu-rays in the same package analogy, targeting .NET Standard 2.0 is like releasing a single disc (let’s call it a “BluDVD”) that’s simultaneously a DVD and Blu-ray disc and can be played in most Blu-ray and DVD players.
When to Choose
This is a simpler but temporary alternative to multi-targeting. It only works if your library is currently targeting .NET Framework 4.7.2 or later. It is a way to buy time while you migrate your applications to .NET 5/6+. You will eventually need to settle on one of the other four choices for your libraries.
Instead of having a single NuGet package with two “substantially similar” libraries, this approach will yield a single library that is “locked” to whatever is available in .NET Framework 4.7.2. That might be okay, depending on the contents of your library.
With multi-targeting, you can introduce additional functionality in the .NET 5/6+ code for new applications. Over time, you have migrated all of your consuming applications to .NET 5/6+, you can simply remove the .NET Framework targeting from your library and return to a simple package. None of this is possible with the .NET Standard “bridge” approach.
How to Execute
This process is basically the same as “update,” though there is a higher chance for errors, which may be motivation to select a different method.
- In your library, change what Visual Studio will target to .NET Standard 2.0.
- Evaluate the errors and incompatibilities that Visual Studio reports.
• Look for errors that will require substantial code changes - Then, either…
• Fix the errors (and test then repeat as needed) and publish the library with the new targeting
or
• Choose another migration method
Related Questions with Resources
It’s easy to end up in a multi-targeting rabbit hole as you research. To save you time, we’ve answered many common questions with some good resources to check out.
What else is multi-targeting good for, besides a way to manage libraries for different platforms?
Multi-targeting is also a mindset for migrating applications. This is what we do with ProGet. You can build an application as .NET 5/6+ AND .NET Framework, then test these versions side-by-side. This lets you deploy the “newer”-platformed version to production, and if there’s a problem, quickly switch to the .NET Framework application. It’s like insurance.
What does multi-targeting look like “in real life”?
To see how to port from one library to another, check out Rick Strahl’s “Multi-targeting and Porting a .NET Library to .NET Core 2.0.” To learn about multi-targeted applications, read Brad Robinson’s “Non-Trivial Multi-Targeting with .NET.”
How can I target in SDK projects?
Microsoft gives us detailed documentation on SDK-style projects.
How do I develop for multiple platforms with .NET Framework?
It’s not terribly difficult, actually! But read Microsoft’s instructions to make sure you get it right.
Can I target multiple operating systems in one NuGet package?
This piece about .NET Standard is a bit dated but gives some instruction. .NET 5/6+ explicitly considers cross-platform development. This Microsoft documentation helps explain this, under the heading “When to Choose .NET 5/6+”
How does this relate to .NET Multi-Targeting Packs?
For the choices we discussed in this article, you do not need to worry about multi-targeting packs. But for those interested, this technical question is best answered by “additional reading” on what a multi-targeting pack even is and guidelines for use.
How does this relate to .NET Multi-platform App UI (MAUI)?
For the choices we discussed in this article, MAUI is unrelated. But for those interested, you can learn more about MAUI via Microsoft.
Hit the Right Target
.NET 5/6+ marks a new era in .NET development. But not all your applications and libraries will be immediately affected. Don’t rush headlong into migrating. Instead, make better decisions—and ultimately use fewer organizational resources—by assessing and planning which libraries should be abandoned, updated, forked, multi-targeted, or bridged.
Get a Copy of the .NET 5/6+ Migration Guide
The migration to .NET 5/6+ from .NET Framework has many complications and, as we’ve discussed, many options for how and when to migrate. We’ve built a guide on how to successfully migrate to .NET 5/6+ and beyond. Get your copy today!