.NET 5 has been available for some time now and .NET 6 will be released in late 2021, but perhaps your team is still using .NET Framework 4.7 or 4.8. You may have preferred to stick with what your team knows, or with the time-tested platform that has been around for decades, but .NET 5 presents a compelling case for those who haven’t made the jump yet. And while it may seem like a small jump in version numbers from 4.x to 5, .NET 5 is a major leap from .NET 4.x and a continuation of the all-new framework that started with .NET Core 1.0 through .NET Core 3.1 and is now the future for all .NET development.
Some of the benefits of migrating to .NET 5:
- Built for performance, and getting faster with every release
- It is the current framework that is being actively developed with regular performance, feature, and security updates
- Using the current framework will mean that future upgrades to .NET 6, 7, and onward will be much easier than the migration from .NET Framework 4.x to .NET 5
- Build and run cross-platform
- Optimized project files for faster load and build times
- Open source on GitHub
- Command Line Interface (CLI) for general use and scripting tasks
- Attract and retain developers who want to work with the latest technologies
Depending on the size of your application, this may be a larger undertaking than any framework upgrade you’ve done in the past, but it also holds greater potential for performance improvements than any prior .NET Framework upgrade. We have helped many clients make this migration, and we have refined the process to make it as painless as possible. Every project has its own constraints and dependencies, so your migration process may be slightly different and require additional steps, but most our .NET 5 migrations follow these steps:
Step 1: .NET Portability Analyzer
The first step in the migration is to analyze your current application to determine the amount of effort to expect when migrating to .NET 5. The .NET Portability Analyzer is a free tool that will analyze your assemblies and provide you with a report of APIs in your current application that are no longer supported. There is typically a path forward for code that uses APIs that are no longer supported, but these changes will require more effort than supported APIs that can easily be shifted to the new version of .NET.
Step 2: Evaluate Project Dependencies
Evaluate dependencies between projects and determine whether to upgrade library classes to .NET Standard or .NET 5. If all projects are being upgraded to .NET 5, then all projects can target .NET 5. In the case where you need to leave a project in .NET Framework and that project needs to reference an upgraded class project, you will need to target .NET Standard 2.0 instead of .NET 5. Refer to the .NET Standard implementation support page to determine what versions of .NET and .NET Standard are compatible with each other.
Step 3: Convert Class Libraries
Class libraries are typically the easiest project types to convert. If they do not have any compatibility warnings in Step 1, it is very likely that you will be able to simply migrate all of the existing code to the new project structure. Before you start converting projects, ensure that you have the desired version of the .NET SDK installed.
When you are ready to migrate your projects, you can start with the Try Convert tool to see if your entire solution or individual projects can be migrated automatically. If that does not succeed, or if you want to convert them manually to have more control over the process, you can take the following approach:
- Create a new Class Library project in either the same folder (with a new project name) a parallel folder (with the same project name) using either Visual Studio (Add > New Project > Class Library), or with the CLI command
dotnet new classlib -o <ProjectName>
- If using the same project name, replace the old csproj class file with the new csproj file that was just created
- Manage Nuget packages for the new project and add any missing packages that your code requires. You can also right-click on the packages.config file in Visual Studio and select “Migrate packages.config to PackageReference.”
- Delete files and folders that may no longer be needed such as the Properties folder and the packages.config file (now that your Nuget packages are now managed in the csproj file)
- Build the project and resolve any missing references or errors
Step 4: Convert ASP.NET Projects
There have been a lot of changes to how .NET Core and .NET 5 initialize and run ASP.NET projects, so this step tends to be more involved than migrating class libraries.
Similar to Step 3, you may be able to automatically convert your entire solution or the ASP.NET projects with the Try Convert tool. But if it does not succeed, or if you want to perform the conversion manually, you can follow these steps:
- Similar to Step 3, create a new ASP.NET project and use the type that fits your project: ASP.NET Core Web API, ASP.NET Core Web App, or even ASP.NET Core Empty if you want to start from scratch. Select “.NET 5” for your Target Framework.
- Review your startup code in Global.asax.cs. Any custom logic will need to be migrated to the new Startup class in .NET 5.
- Copy or move all of your existing controllers and classes into the new project structure
- Update existing API controller classes to derive from Microsoft.AspNetCore.Mvc.ControllerBase. You may want to create your own ApiControllerBase class that derives from ControllerBase and is decorated with the [ApiController] attribute. Controllers that need to provide MVC View support can derive from Microsoft.AspNetCore.Mvc.Controller.
- Resolve any Nuget or reference errors. You will likely need to adjust your
usingstatements to account for changed namespaces in .NET 5.
- Migrate any Handlers to use .NET Middleware instead
- Migrate web.config settings to appsettings.json
- Clean up the old project and any unnecessary files, such as Global.asax, app.config, packages.config
Step 5: Porting Entity Framework 6 to Entity Framework Core 5
If you are using an older version of Entity Framework, this is a good time to at least consider whether you want to migrate to Entity Framework Core 5. Because there are significant changes between EF 6 and EF Core 5, Microsoft refers to this as a “port” rather than a “migration” and it is worth reviewing all of their considerations on the Porting from EF6 to EF Core page. If you do port to EF Core 5, you should plan to test your application to ensure it works and performs as expected. Some queries may need to be adjusted to align with how EF Core handles joins and split queries, and some aspects have changed that will need to be restructured, such as complex Group By queries.
Moving to EF Core 5 does have its advantages, and similar to the rest of the .NET 5 platform, every release adds new capabilities and performance improvements.
If you decide to move to EF Core 5, the typical migration steps are:
- If scaffolding or reverse-engineering your DbContext from a database using the EF Scaffold tool or EF Core Power Tools, set the DbContext target to EF Core 5 and regenerate your models and DbContext files. If you were using an EDMX file, you will need to generate a new DbContext and Models using a scaffolding tool. If you are using Migrations, there is no easy way to port the existing migrations. Instead, you will want to migrate your model to EF Core and then use
Add-Migrationto create a new starting point for future updates and migrations.
- If you are not using Dependency Injection, configure your Context by overriding the OnConfiguring() method
- If you are using Dependency Injection, call the IServiceCollection.AddDbContext() extension method in your Startup ConfigureServices method. You can set the connection string and other configuration options within AddDbContext.
Step 6: Review Dependency Injection
If you are already using Dependency Injection, you can likely continue to use the same DI framework. If you are not using DI at all, the migration to .NET 5 provides the perfect opportunity to start using the built-in Dependency Injection framework. Even if you are using a different DI framework, it may be worth considering making the switch to .NET Dependency Injection because of its excellent performance, and since it is a first-class citizen in .NET, it is very easy to adopt and use.
Step 7: Migrate to System.Text.Json
Similar to EF Core and DI, the migration to System.Text.Json for serialization and deserialization is an optional migration. If you are using Newtonsoft.Json currently, there won’t be complete feature parity in System.Text.Json, so it is worth reviewing the differences outlined here. But if System.Text.Json does provide all of the features you need, it is likely that you will see performance improvements by making the switch.
Here are our typical steps for migrating to System.Text.Json:
- Remove Nuget references to Newtonsoft.Json in your project(s)
- Build your solution and you should get build errors for everything that was using Newtonsoft
- Update using statements, typically removing Newtonsoft.Json and replacing with System.Text.Json
- Update serialization/deserialization syntax: SerializeObject() becomes JsonSerializer.Serialize() and DeserializeObject() becomes JsonSerializer.Deserialize()
Making the move from .NET Framework to the latest .NET platform can be a large effort, but it certainly has its benefits. Along with the immediate performance gains, you will once again be on the current .NET platform that will continue to improve over time.
We have helped many clients make this migration, so let us know if we can help!