What is a .NET Framework to .NET Core migration?
A .NET Framework to .NET Core migration is the work of moving code written for the Windows-only .NET Framework 4.x onto modern, cross-platform .NET. The name is a little dated: Microsoft dropped the word “Core” after version 3.1, so the destination today is simply “.NET”, with .NET 10 as the current long-term support release.
In practice the migration touches four layers. The project files change from the old verbose MSBuild format to the short SDK-style format. The web layer changes from System.Web (ASP.NET MVC 5, Web API 2, Web Forms) to ASP.NET Core with its middleware pipeline. Configuration moves from web.config to appsettings.json and environment variables. And hosting moves from IIS-only to a choice of Kestrel behind IIS, Nginx, a container or a managed service.
The C# you wrote mostly survives. Business logic, LINQ queries, domain classes and Entity Framework models usually port with modest edits. What does not survive untouched are the framework features that modern .NET left behind, which the next sections list one by one.
- Project format: packages.config and old .csproj to PackageReference and SDK-style projects
- Web: System.Web, HTTP modules and handlers to ASP.NET Core middleware
- Config: web.config and ConfigurationManager to appsettings.json and the options pattern
- Hosting: IIS on Windows to Kestrel on Windows, Linux or containers
Why move off .NET Framework 4.8 now if it still works?
Because “still supported” and “still a good place to build” are different things. Microsoft’s support policy page states that .NET Framework 4.5.2 and later is a component of Windows and follows the lifecycle of the Windows version it is installed on; 4.8.1 is the last feature release, and 4.6.2 reaches end of support on 12 January 2027. Nothing new is being added to .NET Framework.
Meanwhile the ecosystem has moved. Popular libraries increasingly ship new versions only for modern .NET, cloud SDKs add features there first, and developers who know Web Forms or WCF configuration are getting harder to hire. Staying put means paying more each year for the same app.
There are practical wins too. Modern .NET runs on Linux, which widens your hosting options and often lowers server bills compared with Windows licences. ASP.NET Core’s request pipeline is lighter than System.Web. And you get dependency injection, structured logging and health checks built in rather than bolted on.
Timing matters for teams who migrated once already: the official support table lists both .NET 8 and .NET 9 ending on 10 November 2026, while .NET 10, released on 11 November 2025, is supported to 14 November 2028. If you are starting a .NET Framework to .NET Core migration today, target .NET 10 directly.
Which .NET Framework features block a migration to .NET Core?
The blockers are a short, well-known list, and Microsoft documents them on its “.NET Framework technologies unavailable on .NET 6+” page. Finding which ones your solution uses is the first job of any audit, because they decide whether a project ports in days or needs a redesign.
ASP.NET Web Forms has no ASP.NET Core equivalent, so ASPX pages, ViewState and server controls must be rebuilt. WCF server hosting is not part of modern .NET, although Microsoft points to the community CoreWCF packages as a route to keep SOAP services alive. Windows Workflow Foundation is not supported either; the documented alternative is the open-source CoreWF project.
Lower down the stack, creating extra AppDomains throws an exception, .NET Remoting is gone (Microsoft suggests pipes, sockets, HTTP or StreamJsonRpc instead), Code Access Security and security transparency are not treated as security boundaries, and System.EnterpriseServices (COM+) is unsupported. Even delegate BeginInvoke and EndInvoke calls throw on modern .NET because they relied on remoting.
Usually a quick fix
ConfigurationManager calls, HttpContext.Current in helpers, old JSON serialisers, BinaryFormatter use in caches, delegate BeginInvoke calls.
Usually a redesign
Web Forms pages with heavy ViewState, WCF duplex services, Workflow Foundation, AppDomain-based plugin loaders, Remoting between processes.
If your solution also has a Windows desktop front end, that part can move to modern .NET while staying on Windows; see desktop application development for that side.
Is the .NET Upgrade Assistant enough for a .NET Core migration?
No tool finishes the job, and the tool most blog posts still recommend has changed status. Microsoft Learn now describes the .NET Upgrade Assistant as officially deprecated and no longer actively developed, recommending the GitHub Copilot app modernization agent instead, and keeping Upgrade Assistant only for environments without Copilot access.
Both tools do useful, mechanical work: converting project files to SDK style, bumping target frameworks, swapping known packages, flagging APIs that will not compile. That saves real hours on a large solution. What they cannot do is decide how to replace a Web Forms grid with custom paging, redesign a WCF duplex callback, or check that an invoice total calculated by the new code matches the old one to the paisa.
We use tooling for the bulk edits and then read every diff. The judgement calls, such as whether a library should target .NET Standard 2.0 or multi-target net48 and net10.0, or whether a SOAP service must stay SOAP because a bank integration calls it, are made by a person who has looked at the callers.
- Tools are good at: project conversion, target framework changes, package swaps, compile error lists
- Tools are weak at: UI rewrites, service redesign, behaviour checks, deployment design
- Always needed: characterisation tests that pin down what the old code does today
A phased .NET Framework to .NET Core migration plan
For any app that has to stay online, the safest route is the one Microsoft itself describes as an implementation of the Strangler Fig pattern: stand up a new ASP.NET Core app, have it proxy unmatched requests to the old ASP.NET app using YARP (Yet Another Reverse Proxy), and move routes across in slices. Users see one site the whole time.
Microsoft’s incremental guide also sets the order for shared code: libraries are upgraded in postorder depth-first sequence, leaves first, main web project last, and only the libraries needed for the routes you are moving right now. The System.Web adapters package, Microsoft.AspNetCore.SystemWebAdapters, lets library code that touches HttpContext compile against both worlds while the move is under way.
- Phase 0, audit: inventory, blocker tags, test gaps, hosting target, written plan
- Phase 1, groundwork: SDK-style projects, PackageReference, dead code removed, warnings fixed, characterisation tests written
- Phase 2, proxy: ASP.NET Core front app with YARP forwarding everything to the old site; shared authentication and session configured
- Phase 3, slices: move a group of routes, compare output, release, repeat
- Phase 4, services: WCF, background jobs and scheduled tasks moved or replaced
- Phase 5, retire: proxy fallback removed, old app switched off, Windows server released if no longer needed
Each phase ends with something running in production. If budget pauses the work after phase 3, you still have a working hybrid, not a half-finished rewrite sitting in a branch.
You rebuild the pages rather than port them, because ASP.NET Core has no ViewState, no page lifecycle events and no server controls. The good news is that the code behind a Web Forms page usually contains the real value, the business rules, and that part can be lifted into services that the new pages call.
There are two sensible targets. Razor Pages suit form-heavy admin screens and public pages: one page, one model, predictable HTML that search engines and screen readers handle well. Blazor suits screens that behave like desktop software, with grids, live filters and component reuse, and it will feel more familiar to a team used to event-driven Web Forms code.
Order matters. We start with low-traffic, low-risk screens to prove the layout, authentication and data access, then move the pages people use every day. GridView-style screens get server-side paging and sorting from the start, since the new version should not load ten thousand rows into memory the way some old grids did.
Choose Razor Pages when
Screens are mostly forms, reports and CRUD, you want plain HTML output, and public pages need to rank in search.
Choose Blazor when
Screens are interactive dashboards used by logged-in staff, you want reusable components, and the team prefers C# over JavaScript.
What happens to WCF services in a .NET Core migration?
It depends on who calls them. WCF client code (calling someone else’s SOAP service) works on modern .NET through the System.ServiceModel client packages. WCF server code, the services you host, is the hard part, and there are three honest options.
Keep SOAP with CoreWCF when outside partners, banks, government portals or hardware vendors call your endpoints and you cannot make them change. CoreWCF is a community port that Microsoft links from its own documentation; it covers the common bindings, though not every exotic configuration, so the audit checks your bindings one by one.
Move to REST with ASP.NET Core minimal APIs or controllers when you own both ends and the callers are your own web or mobile apps. This is usually the cleanest outcome, and the same API can later serve an Android and iOS app. Choose gRPC when two of your own backend services talk to each other at high volume and need strongly typed contracts.
- Partner-facing SOAP endpoint: CoreWCF, same WSDL, callers unchanged
- Internal service consumed by your web front end: REST API
- Service-to-service traffic inside your network: gRPC
- Duplex callbacks or MSMQ bindings: redesign, often with a queue or SignalR
Checking NuGet packages before a .NET Framework to .NET Core migration
Every package in the solution gets one of four labels: already supports modern .NET, has a newer version that does, has a modern replacement, or is abandoned. The fourth group drives cost more than anything else, because abandoned packages either get replaced or their behaviour gets rewritten in your own code.
Common patterns we see in older solutions: Enterprise Library blocks for logging and data access, old versions of report viewers, PDF libraries pinned to a decade-old release, Unity or Ninject containers, and hand-copied DLLs in a lib folder with no package at all. Commercial component suites often have modern versions, but under a new licence, so check your subscription before assuming the upgrade is free.
Microsoft’s own guidance notes that the Windows Compatibility Pack can bridge some Windows-specific APIs such as the registry or event log when the app will stay on Windows. That is a useful stopgap, but anything using it will not run on Linux, so we flag each use in the audit.
Green
Package has a current release targeting .NET Standard 2.0 or modern .NET. Update and move on.
Amber
A replacement exists with a different API, for example a new logging library. Budget adapter work.
Red
Abandoned, closed-source or Windows-only. Replace or rewrite, and price it separately.
Entity Framework, authentication and session during the move
Data access is usually the least dramatic part. Entity Framework 6 can run on modern .NET, which means you can move the web layer first and upgrade to EF Core later, rather than changing the web framework and the ORM in the same release. When EF Core does come, we compare generated SQL on the heavy queries, because lazy loading and query translation differ.
Authentication needs a plan before the first route moves. During an incremental migration users must stay signed in whether a request lands on the old app or the new one. Microsoft’s System.Web adapters include a remote authentication feature where the ASP.NET Core app defers sign-in to the original app, and a remote session feature for apps that store data in Session.
Once everything has moved, sign-in shifts fully to ASP.NET Core Identity, cookie authentication or your identity provider through OpenID Connect. Old ASP.NET Membership password hashes need a compatibility step so existing users can still log in; we verify on the first successful login and store a modern hash from then on.
Moving a migrated .NET app to Linux or containers
Linux hosting is one of the main reasons people start a .NET Framework to .NET Core migration, and it only works if Windows-only code is gone. Before switching the server, we search for registry access, file paths with backslashes, case-sensitive file names, Windows authentication, printer or COM calls, and time-zone IDs that differ between Windows and Linux.
The usual setup is Kestrel behind Nginx on a Linux virtual machine, or the app in a container on a managed platform. Azure App Service for Linux, AWS or Google Cloud all run modern .NET; the choice depends on where your database and other services already live. For teams that want more orchestration, a container setup can grow into Kubernetes later, which our Kubernetes consulting page covers.
Some apps should stay on Windows for now, for example one that talks to a Windows-only driver or relies on Windows authentication inside an office network. That is fine: modern .NET still runs on Windows Server and IIS, and you keep the runtime benefits while deciding about Linux later.
- Replace registry reads with configuration or environment variables
- Normalise file paths with Path.Combine and check file-name casing
- Swap Windows time-zone IDs or use TimeZoneInfo conversions that work on both
- Move Windows authentication to OpenID Connect if the app leaves the domain
How long does a .NET Framework to .NET Core migration take and what drives cost?
A mid-sized business application usually takes 6–12 weeks with our team, and custom software work starts at ₹60,000. A single clean Web API can move in a couple of weeks; a solution with sixty Web Forms pages, three WCF services and a Windows service can run past three months if done in one stretch, which is why we split it into phases you approve one at a time.
The cost drivers are easier to predict than people expect once the audit is done. Count the Web Forms pages and group them by complexity. Count WCF endpoints and note which ones outside callers use. Mark red-label packages. Measure test coverage, which is often zero, and budget the characterisation tests that make every later step safe. Add the hosting change if you want Linux or containers.
What we avoid is quoting a large migration from a single phone call. You get an itemised estimate in about two working days after we see the solution, and the first phase is small enough that you can judge the working style before committing to the rest.
Risks and red flags in a .NET Framework to .NET Core migration
The biggest risk in any .NET Framework to .NET Core migration is behaviour drift: the new code compiles, passes a quick click-through and still calculates something differently. Rounding in GST totals, date handling around midnight, culture-specific number formatting and string comparison rules are the usual culprits. Characterisation tests that feed the old and new code the same inputs are the defence.
Watch for these red flags when you compare proposals. A promise of “zero code changes” is not realistic for a web app. A plan that starts with rewriting the UI before anyone has read the WCF bindings is upside down. A fixed end date given before the audit, or no mention of how users stay signed in during the switch, suggests the hard parts have not been thought about.
There are also red flags on your side. If nobody can tell us how the production server is configured, or the only copy of the source is on one developer’s laptop, we start by recovering and versioning the code. That is not glamorous work, but a migration cannot begin without it.
- No audit before a quote
- Big-bang cutover on a weekend with no rollback plan
- No mention of authentication or session sharing
- Business rules re-typed from screenshots instead of moved from code
- Target runtime chosen without checking support dates
Code ownership, handover and working with us remotely
Your repository, your cloud account, your domain: a .NET Framework to .NET Core migration should never leave you dependent on the people who did it. We work in a Git repository you own or that we transfer to you, deploy to servers billed to you, and hand over admin access at the end. Nothing lives on our personal accounts once the project closes.
Day to day you deal with the three of us directly. One of us handles the full-stack migration work, from controllers to Razor or Blazor screens. Another of us looks after cloud hosting, Linux servers, data and monitoring. The third of us runs the phase plan, tracks decisions and keeps the audit document current. Updates come on WhatsApp seven days a week, in English or Hindi, with calls when a decision needs discussing.
Handover includes a short architecture note, the list of what changed and why, how to build and deploy, where logs go, and what still carries risk. We do not visit your office, we do not supply twenty developers for a large programme, and we do not give licensing advice on commercial components; we tell you what we see and you decide.
.NET Framework to .NET Core migration across India
Plenty of Indian businesses run on .NET Framework without thinking about it: a distributor’s order portal in Ahmedabad, an HR system at a manufacturer near Pune, a hospital billing screen in Kochi, a school fee module in Indore. Many were built between 2008 and 2018 by an IT vendor who has since moved on.
We work remotely with clients in Bengaluru, Hyderabad, Chennai, Noida, Coimbatore and smaller cities alike. The process is the same everywhere: you share repository access, we audit, you approve a phase. Invoices come with GST details for businesses that need them, payment is by UPI or bank transfer, and international clients pay in USD by Wise, wire or PayPal.
Indian apps often have specific quirks worth checking early: GST calculation code spread across stored procedures, Tally or ERP export jobs, SMS gateway calls written for an old API, and reports that print on pre-printed stationery. Each of these gets a line in the audit, because a migration that breaks the monthly GST report will be noticed quickly.
Pre-migration checklist for a .NET Core move
Work through this list before anyone writes new code for your .NET Framework to .NET Core migration. Most items take minutes; together they decide whether the project runs smoothly or keeps hitting surprises. If you cannot answer some of them, that is normal, and finding the answers is part of our audit.
- Is all source code in version control, and does it build on a clean machine?
- Which .NET Framework version does each project target today?
- How many Web Forms pages, MVC controllers and Web API controllers are there?
- Which WCF services exist, and who calls each one from outside?
- Which NuGet packages or loose DLLs have no modern version?
- Is there any Workflow Foundation, Remoting, COM+ or AppDomain code?
- How do users sign in, and where is session data stored?
- What automated tests exist, and do they pass?
- Which scheduled tasks or Windows services run beside the web app?
- Where should the migrated app run: Windows, Linux, containers, which cloud?
Bring whatever answers you have to a first WhatsApp conversation. The unanswered ones become the first week of work, and they are also where most migration surprises hide.
Worked example: a hypothetical distributor portal on .NET Framework 4.7.2
Say a pharmaceutical distributor in Hyderabad runs a dealer portal built in 2014: ASP.NET MVC 5 for the dealer screens, twelve Web Forms admin pages, one WCF service that the warehouse scanner software calls, Entity Framework 6 over SQL Server, and a Windows service that emails invoices every night. It runs on a single Windows server that is due for replacement.
The audit would likely tag the MVC screens as green, the Web Forms admin pages as a Razor Pages rebuild, the WCF service as CoreWCF (the scanner vendor will not change its client), and the Windows service as a hosted background service inside the new app. We would propose starting from ₹60,000, split into four phases, each quoted separately.
Weeks one and two: groundwork, SDK-style projects, tests that capture invoice totals and scheme discounts for a sample of real orders, and the ASP.NET Core front app with YARP. Weeks three to six: dealer screens moved in three batches, each compared against old output. Weeks seven to nine: admin pages rebuilt, CoreWCF endpoint stood up and tested against the scanner software on staging. Weeks ten and eleven: nightly invoice job moved, old server retired, app running on Linux. This is an illustration of how we would plan it, not a past project.