Many business-critical systems still run on .NET Framework 4.x. They work, but they are harder to host, harder to hire for and cut off from most of the improvements Microsoft has shipped since .NET Core. This guide explains how to plan a .NET Framework to .NET migration that keeps the business running while you move.
Why migrate now
- Performance and hosting: modern .NET is cross-platform, runs well in Linux containers and is significantly more efficient for web workloads.
- Long-term support: .NET 10 is the current long-term support (LTS) release, supported for three years from November 2025. See Microsoft's .NET support policy.
- Ecosystem: most new libraries, SDKs and tooling target modern .NET first — or only.
- Hiring: developers want to work on current technology; a modern stack makes recruiting easier.
Step 1: Assess what you have
Start with an inventory, not code changes:
- List every project, its type (class library, web app, WCF service, Windows service, desktop) and its target framework.
- List NuGet dependencies and check whether each has a modern .NET version.
- Identify use of APIs that do not exist in modern .NET:
System.Web, WCF server hosting, .NET Remoting, AppDomains, some Windows-specific APIs. - Measure test coverage around critical business flows.
Microsoft's porting documentation and the .NET Upgrade Assistant help with this analysis. The output should be a map of "easy", "needs work" and "needs redesign" components.
Step 2: Choose the strategy — incremental beats big-bang
A full rewrite freezes feature development and risks losing undocumented business rules. For anything non-trivial we recommend the strangler fig pattern: put a routing layer (for example YARP, an Azure Application Gateway or a reverse proxy) in front of the legacy application, build new functionality in ASP.NET Core, and move routes across one at a time. The old system shrinks until it can be switched off.
Rule of thumb: migrate the libraries first, then the services, and the web UI last. Shared business logic moved to .NET Standard 2.0 or multi-targeted projects can be used by both the old and new applications during the transition.
Step 3: Stabilize with tests
Before moving code, add tests around the behaviour you must not break: calculations, pricing, permissions, integrations. Characterization tests — tests that record what the system does today, even if it is odd — are especially valuable for legacy code.
Step 4: Migrate project by project
Class libraries
Convert to SDK-style project files, retarget, update NuGet packages and fix compile errors. Multi-target (net48;net10.0) where both applications still consume the library.
Web applications
ASP.NET MVC applications map reasonably well to ASP.NET Core MVC: controllers and views carry over with changes to startup, configuration, routing, authentication and dependency injection. WebForms has no direct equivalent — plan to rebuild those pages with Razor Pages, Blazor or a separate front end while reusing the business layer.
WCF services
Choose between CoreWCF (lowest change for existing SOAP clients), gRPC (efficient service-to-service calls) or REST APIs with ASP.NET Core (broadest compatibility). Often the answer is REST for new consumers and CoreWCF temporarily for existing ones.
Configuration and hosting
Replace web.config app settings with appsettings.json, environment variables and a secrets store such as Azure Key Vault. Move from IIS-only hosting to Kestrel behind IIS, containers or a managed platform.
Step 5: Data access
Entity Framework 6 runs on modern .NET, which lets you migrate the application first and move to EF Core later. When you do move to EF Core, review lazy-loading behaviour, raw SQL and stored procedure usage carefully — they are common sources of subtle differences.
Step 6: Roll out safely
- Deploy new components behind feature flags or route-by-route in the proxy.
- Monitor errors and performance side by side with the legacy system.
- Keep a rollback path for every step.
- Decommission legacy components only when traffic and dependencies reach zero.
Common pitfalls
- Underestimating
System.Webdependencies hidden in shared libraries. - Changing behaviour and platform at the same time — migrate first, improve second.
- Skipping authentication and session differences between ASP.NET and ASP.NET Core.
- No owner for the old system during the transition, so it quietly accumulates new features.
Key takeaways: assess before you code, migrate incrementally with the strangler fig pattern, protect behaviour with tests, and move the web layer last. Our .NET 10 upgrade guide covers what you gain once you get there.
Planning a migration? Our legacy application modernization team starts with a written assessment and a staged plan. Book a consultation to discuss your system.



