This guide is for the person responsible for a business application built on .NET Framework, Microsoft’s original Windows-only platform, who has been told it should move to modern .NET. It covers whether the move is needed, what carries across, the order of the work and where it usually gets stuck.
The target is .NET 10, the current long-term support release. It came out in November 2025 and is supported until 14 November 2028. .NET 8 and .NET 9 both reach end of support on 10 November 2026, so a project starting now should not aim for either. Microsoft releases a new version every November and gives the even-numbered ones three years of support, so allow for another move before November 2028. Going from one modern version to the next is a far smaller job than leaving .NET Framework. Our .NET end of support page has the dates.
Before you start
Check that the application has to move. .NET Framework 4.8 and 4.8.1 are supported for as long as the version of Windows they run on. They receive security fixes and no new features. Microsoft’s guidance says that in most cases an existing application does not need to migrate. An application that is stable and rarely changed can reasonably stay on 4.8. The usual reasons to move are that a component you depend on has dropped .NET Framework, or that the application will be under active development for years.
Find out what it is built from. Some .NET Framework technology was never carried forward. This is Microsoft’s own position on the usual blockers:
| Technology | On modern .NET | What Microsoft points to |
|---|---|---|
| Windows Forms and WPF desktop applications | Available, on Windows only | Upgrade the project. Third-party controls may not have been ported |
| ASP.NET MVC and Web API | Replaced by ASP.NET Core | A port to a different application model |
| ASP.NET Web Forms | Not available | Staying on .NET Framework, or rewriting the pages (step 5) |
| WCF services other systems call (the server side) | Not part of .NET itself | The CoreWCF NuGet packages |
| Windows Workflow Foundation | Not supported | CoreWF, as an alternative |
| .NET Remoting | Not supported | Pipes, StreamJsonRpc or HTTP services |
| Creating AppDomains | Not supported | Separate processes or containers |
Calling an existing WCF service from modern .NET is still possible: Visual Studio’s WCF Web Service Reference tool generates the client code.
Have in hand the complete source code in a state that builds, a list of third-party components with their licences, whatever automated tests exist and someone who knows the application well enough to test it.
Know what the tools do. Microsoft has deprecated the .NET Upgrade Assistant and says to use it only where GitHub Copilot is not available. Its replacement is a GitHub Copilot agent built into Visual Studio 2026 and recent updates of Visual Studio 2022. Microsoft’s pages currently use more than one name for it: the porting overview calls it GitHub Copilot app modernization, and the agent’s own page, updated in September 2026, calls it GitHub Copilot upgrade. According to Microsoft it assesses the code and its dependencies, writes an upgrade plan you can adjust, makes the changes and checks that the application builds and its tests pass. Treat it as help with the mechanical conversion. It does not decide what to do about anything in the table above, and its output still needs review and testing.
How the effort divides depends on the front end. Steps 1 and 2 are small and step 3 is usually moderate. Each can go to production on its own. A Web Forms front end or a set of WCF services is usually the largest part of the work, because it is rewritten and not converted.
1. Get every project onto .NET Framework 4.8
Microsoft recommends retargeting to at least .NET Framework 4.7.2 before porting, so that the newest API alternatives are available. We go to 4.8, because it is the version to be on if the migration stops part-way. Later 4.x versions are in-place updates, so this is usually a small change, and it has to happen anyway for anything on 4.6.2, which goes out of support on 12 January 2027.
2. Inventory packages and third-party components
NuGet is the service .NET projects download their libraries from. For every NuGet package and every bought-in component, such as a grid or a reporting engine, find out whether a version for modern .NET or .NET Standard exists. The package’s page on nuget.org lists the frameworks it supports. Microsoft’s guidance is to do the following while still on .NET Framework:
- Update each package to the latest version that works.
- Convert
packages.configto the PackageReference format, because modern .NET cannot usepackages.config. - Convert project files to the newer SDK-style format, which works with .NET Framework as well.
A component with no modern version needs a replacement or a decision, and that decision is better made now than half-way through.
3. Move the class libraries first
Class libraries hold the business logic and data access. Microsoft’s guidance is to start with the libraries that depend on nothing else in the solution, work upwards and leave the application itself until last.
Target .NET Standard 2.0, the last version of that specification .NET Framework supports, or build the library for both platforms at once (multi-targeting). Either way the old application carries on using the same library while the new one is built against it. Where code calls Windows-only APIs such as the Registry, Microsoft’s Windows Compatibility Pack supplies a large part of the missing .NET Framework surface.
4. Move the application shell
A Windows Forms or WPF application is converted in place and tested on Windows.
For a web application, Microsoft describes two paths. An in-place migration replaces the whole application at once and suits small ones. For larger applications, or any that must stay in production throughout, Microsoft recommends what it calls incremental migration, an implementation of the Strangler Fig pattern:
- A new ASP.NET Core application is placed in front of the old one.
- It forwards every request it cannot yet handle to the old application, using a reverse proxy called YARP.
- Routes are moved across a few at a time.
- When nothing is forwarded any longer, the old application is retired.
Microsoft’s System.Web adapters, from the dotnet/systemweb-adapters project, support this. They let shared libraries that use HttpContext, the object holding the current web request, run under both applications, and let the two share sign-in and session state.
5. Decide what to do with a Web Forms front end
Web Forms exists only on .NET Framework, so there are two honest options.
- Keep it on 4.8. The libraries beneath it can still be modernised, and new features can be written in ASP.NET Core alongside.
- Rewrite it screen by screen behind the proxy described in step 4, starting with the pages that change most.
Microsoft’s Copilot agent lists a scenario for converting Web Forms to Blazor, its current framework for web screens written in C#. We would treat what it produces as a first draft. Our ASP.NET Web Forms page goes through the options in more detail.
6. Keep Entity Framework 6 for now
Entity Framework is the library many .NET applications use to talk to the database. Version 6 runs on modern .NET and Microsoft describes it as stable and supported, though no longer actively developed. EF Core, its successor, is a rewrite with no direct upgrade path. It does not run on .NET Framework and does not read the EDMX model files that older applications use.
Microsoft points out that you can move to modern .NET while keeping EF6, then deal with EF Core as a separate piece of work. We would do it in that order, because doing both at once changes the platform and every database query together.
7. Test and run old and new side by side
Both versions work against the same database, so their output can be compared screen by screen and report by report. With the incremental approach the old application never leaves production. Each route is switched over when it has been tested, and switching it back is a change to the proxy. For a desktop application, give the new build to a few users first while everyone else stays on the old one.
What usually goes wrong
- A third-party component with no modern version is found late.
HttpContextand other System.Web types are used throughout the business logic, which Microsoft lists first among the obstacles.- Sign-in and session state behave differently between the old and new applications during an incremental migration.
- EF Core is attempted in the same step as the platform move.
- The tool’s output is treated as finished work.
- The migration stalls half-way, and two code bases have to be maintained.
When to get help
Get help when nobody can say how large the job is, or when a board wants a sized plan before approving a budget. Our fixed-price .NET upgrade assessment produces that plan: what moves easily, what has to be replaced and the stages in order. If its conclusion is that the application should stay on .NET Framework 4.8, the report says so.
Sources
- Overview of upgrading .NET apps
- Overview of porting from .NET Framework to .NET
- .NET Framework technologies unavailable on .NET
- .NET vs. .NET Framework for server apps
- What is .NET Upgrade Assistant?
- What is GitHub Copilot upgrade?
- Prerequisites to porting code
- Analyze your dependencies to port code from .NET Framework to .NET
- .NET Standard
- Migrate from ASP.NET Framework to ASP.NET Core
- Get started with incremental ASP.NET to ASP.NET Core migration
- System.Web adapters
- Blazor for ASP.NET Web Forms developers
- Use the WCF Web Service Reference Provider Tool
- Compare EF Core and EF6
- Port from EF6 to EF Core
- Lifecycle FAQ: .NET Framework
- Microsoft .NET and .NET Core lifecycle
- .NET and .NET Core official support policy