You cannot upgrade ASP.NET Web Forms to ASP.NET Core in place. Web Forms was never ported to .NET Core or modern .NET, so moving to .NET 10 means rebuilding the UI in Blazor, Razor Pages, MVC or a JavaScript front end such as React. Pick the target by team skills and how interactive your screens are, then migrate one page at a time behind a YARP proxy instead of attempting a big-bang rewrite.
Can Web Forms run on .NET 10?
No. Microsoft’s guide Blazor for ASP.NET Web Forms developers explains that the .NET team decided against porting Web Forms to .NET Core because the breaking changes required were too drastic. Web Forms stays a Windows-only part of .NET Framework 4.8.x.
That does not make it unsupported today. Microsoft’s position is that Web Forms remains supported for as long as .NET Framework ships with Windows. The pressure to move usually comes from hosting, hiring, security reviews and the rising cost of every change.
Microsoft now ships tooling for the move. Its documentation for the GitHub Copilot upgrade agent, updated in September 2026, lists a WebForms-to-Blazor scenario that converts pages, controls and code-behind into Blazor Server components. I look at what that tooling does well and where it needs a human in my review of Copilot app modernization for .NET.
What happens to ViewState, postbacks and UpdatePanels?
The C# in your code-behind usually ports with modest changes. The page model is what has to be rethought. This table shows where each Web Forms feature lands in the three main targets.
| Web Forms feature | Blazor | Razor Pages / MVC | React + ASP.NET Core API |
|---|---|---|---|
| ViewState | Component state in memory, on the server circuit or in the browser | No equivalent. Reload data per request or use hidden fields | Client-side state in components |
Postbacks and server events (Button_Click) | @onclick handlers. The closest match | Form POST to a page handler or controller action | API calls from the browser |
| UpdatePanel partial refresh | Built in. Components re-render only what changed | A small script, or a Blazor component embedded in the page | Normal SPA behaviour |
| User controls (.ascx) | Razor components | Partial views, view components, tag helpers | React components |
| Server controls (GridView, Repeater) | Component libraries or hand-built tables | Tag helpers and plain HTML | Component libraries |
| Code-behind and the page lifecycle | @code block or a .razor.cs partial class | PageModel class or controller | Split between components and API controllers |
| Master pages | Layouts | _Layout.cshtml | Layout components |
ViewState deserves a specific warning. Web Forms pages often keep lookups, selected rows and even business data in ViewState between postbacks. Blazor Server keeps equivalent state in a server-side circuit for each browser tab. That feels familiar, but it costs server memory, and the state is lost if the connection stays down too long. Razor Pages has no page state at all, so each request rebuilds what it needs. Find out what your pages keep in ViewState before you choose.
Session is the other trap. Microsoft’s Copilot upgrade documentation includes a skill dedicated to Blazor Server problems such as a null Session inside WebSocket circuits and lost wizard or cart state. Expect to redesign anything that leans heavily on Session.
Should you use Blazor Server, Blazor WebAssembly or static rendering?
Since .NET 8, Blazor is chosen per component through render modes. Static server rendering produces plain HTML with no interactivity. Interactive Server runs components on the server over a SignalR connection. Interactive WebAssembly runs them in the browser. Interactive Auto starts on the server and switches to WebAssembly once the bundle has downloaded.
Microsoft lists four Blazor Server limitations. Every user interaction is a network hop, there is no offline support, scaling to many users needs server resources for each connection, and you need an ASP.NET Core server to host it. Blazor WebAssembly reverses those trade-offs with a larger download, code that users can inspect, and the option of hosting the whole app as static files.
For an internal line-of-business app on a reliable network, Interactive Server is the closest match to how Web Forms developers already think. It is also the target of Microsoft’s Copilot WebForms scenario.
When are Razor Pages or MVC the better choice?
Razor Pages is a page-based, server-rendered model. Each page has its own handler class, and the HTML arrives ready to display. For Web Forms apps that are mostly forms, lists and reports, it is often the simplest target. It needs no persistent connection, scales like any web app and gives search engines complete HTML.
Choose MVC when the app already mixes pages with Web API endpoints, or when your developers know MVC well. In both cases you can drop an interactive Blazor component into a page where one screen needs rich behaviour. Microsoft designed MVC, Razor Pages and Blazor to be used together.
When does React make sense for a Web Forms migration?
React with an ASP.NET Core API fits when you already employ front-end developers, the UI is highly interactive, or the same API will serve a mobile app or partners. Microsoft’s own comparison names the downsides: more languages, frameworks and tools, and logic that is hard to share between client and server. For a C# team rescuing a Web Forms app, that can mean running two migrations at once.
If public pages need to rank in search, plan server-side rendering from the start, for example with Next.js. A client-only React app serves an empty shell until its JavaScript runs.
How do you choose between Blazor, Razor Pages and React?
| Factor | Blazor Server | Blazor WebAssembly | Razor Pages / MVC | React + API |
|---|---|---|---|---|
| Team skills | C# only | C# only | C# and HTML | C# plus TypeScript and React |
| UI complexity | Rich, stateful screens | Rich screens, offline possible | Forms, lists, reports | Rich, client-heavy apps |
| Interactivity | High, via server round trips | High, in the browser | Low to medium | High, in the browser |
| SEO | Good with prerendering, which is on by default | Weak unless a server prerenders | Strong, full HTML | Needs a server-rendering framework |
| Hosting | ASP.NET Core server holding a connection per tab; Azure SignalR Service at scale | Static files or a CDN when standalone | Any ASP.NET Core host | Static front end plus an API host |
| Distance from Web Forms | Closest | Close | Moderate | Furthest |
You can mix them. A sensible outcome for many line-of-business apps is Razor Pages for public and simple pages, with Blazor components for the few screens that need rich interaction.
How do you migrate Web Forms without a big-bang rewrite?
For large production apps, Microsoft recommends incremental migration, which its documentation describes as an implementation of the strangler fig pattern. A new ASP.NET Core app sits in front of the old one and forwards every request it cannot handle yet to the Web Forms app, using YARP, Microsoft’s reverse proxy library. Pages move across one at a time. Users see a single site throughout.
- Stand up the proxy. Create the ASP.NET Core app with YARP forwarding all traffic to the existing site, and put it into production before you migrate anything.
- Share authentication and session. The System.Web adapters let the new app defer authentication to the old one and share session state, so users stay signed in as they move between old and new pages.
- Upgrade shared libraries in order. Move class libraries to .NET Standard 2.0, or multi-target them, starting with those that depend on nothing else. Swapping the System.Web reference for the
Microsoft.AspNetCore.SystemWebAdapterspackage keeps code that usesHttpContextcompiling. - Pin down each page before moving it. Record what the page does today with characterisation tests: inputs, outputs, database changes and emails sent.
- Move a page, switch the route, repeat. When the new page passes the recorded tests, route it to ASP.NET Core. Rolling back is a routing change.
- Retire the old app when nothing routes to it any more.
Take a hypothetical 120,000-line Web Forms app with 150 pages. A big-bang rewrite freezes features for months and goes live in one risky weekend. The strangler approach lets the team ship the ten most-used pages first, learn from them, and keep fixing the remaining old pages until their turn comes.
Where does AI help in a Web Forms migration?
AI agents are good at the mechanical part, such as turning a GridView and its code-behind into a component or an event handler into a page handler. They cannot know which ViewState quirk a user relies on. That is why I pair agents with recorded behaviour and review every change before it merges.
The Modernisation Blueprint applies this to one real page of your application in two weeks as a fixed-price package from £20,000. You get the migrated page with passing characterisation tests, a target architecture and a fixed price for the rest.
Choose the target page by page if you need to, but choose the migration method once: a proxy in front, tests before each move, and the old app retired only when nothing routes to it.
Sources
- Microsoft Learn: An introduction to Blazor for ASP.NET Web Forms developers
- Microsoft Learn: Migrate from ASP.NET Framework to ASP.NET Core
- Microsoft Learn: Get started with incremental ASP.NET to ASP.NET Core migration
- GitHub: dotnet/systemweb-adapters
- Microsoft Learn: Get started with YARP
- Microsoft Learn: ASP.NET Core Blazor render modes
- Microsoft Learn: ASP.NET Core Blazor hosting models
- Microsoft Learn: Choose an ASP.NET Core UI
- Microsoft Learn: .NET upgrade scenarios and skills (GitHub Copilot upgrade)