Migration guide
WebForms & .NET Framework → .NET 10 Checklist
A step-by-step checklist for modernizing legacy .NET — inventory, target selection, honest tooling, bottom-up sequencing, parity testing, EF6 to EF Core, and cutover.
Last updated Jul 26, 2026
.NET Framework 4.8 still runs — but everything around it is moving on: the free migration tooling is retired, .NET 8 and 9 leave support on November 10, 2026, and every year on WebForms shrinks your hiring pool. This is the checklist we run in client modernization engagements. Work it top to bottom; every unchecked box is schedule risk.
1. Inventory the solution
Migrations fail on surprises, and surprises live in the inventory you didn’t take:
- List every project with its target framework, and map the dependency graph between them — the graph, not the folder structure, dictates migration order.
- Audit NuGet packages: which have .NET 10-compatible versions, which have successors, which are abandoned. Abandoned packages with no successor are your first blockers.
- Measure the WCF surface: services, bindings, security modes, and which clients call them. Message-layer security and exotic bindings need special handling.
- Count WebForms pages and controls — especially third-party suites (Telerik, DevExpress, Infragistics) and custom server controls, which have no automatic translation.
- Be honest about test coverage. If behavior isn’t pinned by tests today, parity verification (step 5) becomes the migration’s biggest work item.
- Map integration seams: file drops, MSMQ, scheduled tasks, COM interop, registry reads — the things that only surface in production.
2. Pick your targets
- Runtime: .NET 10 LTS (supported to November 2028). Don’t target 8 or 9 — both leave support on November 10, 2026, and you’d be migrating twice.
- Web UI: decide per-app between Blazor (C#-first teams, forms-heavy screens), API-first with the existing UI strangled gradually, or a SPA rewrite if you already own frontend capacity.
- Data: EF6 → EF Core (see step 6), or Dapper where the EF surface was thin anyway.
- WCF: CoreWCF for compatible contracts you want moved cheaply; gRPC or REST for services that deserved a redesign anyway.
3. Be honest about tooling
The free, deterministic .NET Upgrade Assistant was deprecated in late 2025 — it still hides behind a disabled-by-default setting in Visual Studio 2026, but it’s frozen. Its successor, GitHub Copilot app modernization, requires a paid Copilot plan and is non-deterministic: useful for the mechanical share, unreliable on large, undocumented, or unconventional codebases.
Plan accordingly:
- Treat AI output as a draft, not a result: every change goes through a build gate, a test gate, and human review.
- Budget for the last mile. Package swaps and namespace changes are the easy 70%; verifying business behavior, untangling undocumented patterns, and deciding what to redesign is the project.
- Keep migrations replayable: script what can be scripted so a failed attempt costs hours, not the branch.
Doing this under a deadline? We run this checklist as a fixed-scope Modernization Readiness Assessment — inventory, blockers, parity strategy, and a sprint-level plan, from $4,800.
4. Sequence bottom-up
- Start with leaf class libraries: move them to .NET Standard 2.0 or multi-target (
net48;net10.0) so old and new worlds share code during the transition. - Break circular dependencies first — they block multi-targeting and they were a design smell on .NET Framework too.
- Migrate services and background jobs before UIs; they have the clearest contracts to verify.
- Use a strangler-fig on the web surface: route converted sections to the new app, keep the rest on WebForms, retire pages incrementally. Shipping value mid-migration is what keeps the program funded.
5. Build the parity harness
The migration’s real deliverable isn’t compiling code — it’s identical behavior:
- Golden-master tests: capture current outputs (reports, invoices, exports, API responses) as fixtures and diff the migrated system against them.
- Request/response capture: record real production traffic shapes and replay them against the new stack.
- Watch the quiet killers: culture and encoding defaults, date/decimal rounding, sort stability — categories where .NET Framework and modern .NET disagree without throwing.
- Run old and new side by side on the same inputs wherever the architecture allows; a diff report beats a code review for behavioral confidence.
6. Migrate the data layer
EF6 → EF Core is a behavior change, not a package swap:
- Query translation differs — expressions that ran in memory under EF6 may translate to SQL (or throw) under EF Core, and vice versa. Re-verify every non-trivial query.
- Lazy loading is opt-in and proxied differently; navigation-property access patterns that silently worked may now return null or N+1.
- Cascade delete configuration and transaction behavior deserve an audit — the defaults are closer than folklore suggests, but anything relying on SaveChanges ordering or implicit transaction scope needs verification.
- Verify GroupBy and date arithmetic against production-shape data volumes, not seed data — translation quality decisions only show up at scale.
7. Cut over and right-size the infrastructure
- Hosting changes shape: IIS app pools become Kestrel behind a reverse proxy or containers; web.config becomes appsettings + environment; and both machineKey material (now ASP.NET Core Data Protection) and session state (now session middleware over a distributed cache) need explicit replacements.
- Wire observability before cutover — you want baseline metrics from the old system to compare against, not just green checks on the new one.
- Modern .NET runs anywhere, so re-quote your infrastructure: client migrations we’ve run land at 60–90% cost reductions, and our own template re-platform did better still — 94%, with 92% faster compute. Where you land depends on how much of the old bill was managed-service premium.
- Decommission on a date. A frozen .NET Framework deployment kept “just in case” is unpatched attack surface with a licensing bill.
Last updated July 2026 — verified against .NET 10 LTS and current Visual Studio 2026 tooling. Rather hand this list to someone who has run it before? Book an $80 session — it counts toward the assessment.
Frequently asked questions
Can we still run .NET Framework 4.8 in production?
Yes — 4.8 ships with Windows and keeps receiving security patches, so it isn't end-of-life the way IdentityServer4 or .NET Core 3.1 are. The pressure comes from everything around it: no new features, Windows-only hosting, a shrinking hiring pool for WebForms, and third-party packages that stopped targeting Framework years ago. You can run it; you just pay a growing tax for every year you do.
What replaced the .NET Upgrade Assistant?
Microsoft deprecated the free .NET Upgrade Assistant in late 2025. Its replacement is GitHub Copilot app modernization — an AI agent in Visual Studio that requires a paid Copilot plan (Pro, Business, or Enterprise). The old tool still exists behind a disabled-by-default setting in Visual Studio 2026 but is no longer developed. Practically: plan for AI-assisted-but-human-verified migration work, not a free push-button upgrade.
Should WebForms go to Blazor or something else?
Blazor is the natural target when your team is C#-first and the app is forms-and-tables heavy — the component model maps well and server-side Blazor keeps the programming feel familiar. An API-first split (modern backend now, UI decision later) is often smarter when the risk lives in the business logic rather than the UI. A JavaScript SPA rewrite only pays if you already have frontend capacity. The wrong answer is rewriting everything at once.
How long does a .NET Framework to .NET 10 migration take?
Class libraries and services usually move in weeks; WebForms UIs and heavily customized data layers set the real timeline. A small internal app is a weeks-scale project; a mid-size line-of-business system is typically several months — but sequenced correctly (libraries first, strangler-fig on the web surface) you ship working increments the whole way instead of gambling on a big bang.
Is .NET 8 still safe to stay on?
For now — but .NET 8 and .NET 9 both reach end of support on November 10, 2026, after which neither receives security patches. .NET 10 is the current LTS, supported to November 2028. The 8-to-10 jump is far smaller than leaving .NET Framework, so schedule it as routine maintenance this year rather than emergency work next year.
Deep dives in this cluster
4 posts sharing this guide's themes.
Leaving the hyperscalers: what a .NET SaaS really saves moving from AWS/Azure to Hetzner
A line-by-line look at what AWS and Azure actually cost a SaaS in 2026, why the bill scales with your success, and the honest economics of moving to Hetzner.
GitHub Copilot modernize-dotnet vs. Claude Code on a real .NET 8 → 10 migration
Same model, three tools, one migration — measured. What Copilot's upgrade agent, plain Claude Code, and a guarded setup actually delivered, warts included.
The N+1 Query Problem in EF Core: Benchmarking Every Fix on PostgreSQL
Actual BenchmarkDotNet numbers for N+1 vs Include, split queries, projections, and compiled queries in EF Core 10 on PostgreSQL 16.
Why You Need to Migrate from .NET to .NET Core for Software Development
Discover the benefits of migrating from .NET to .NET Core for enhanced performance, cross-platform capabilities, improved security, and modern cloud-native development.