- Audit dependencies first. System.Web, WCF servers and old NuGet packages decide the effort.
- Move class libraries first, then the web layer, with the old and new app running side by side.
- Web Forms has no direct path, so plan those pages as a rewrite or a staged replacement.
- Tests, logging and a rollback route matter more than any conversion tool.
Why teams are moving at all
ASP.NET Framework still runs thousands of business systems in Pakistan, from hospital portals to distributor billing screens. Nothing dramatic happens if yours keeps running. The pressure is quieter. Microsoft ships the Framework as a Windows component and does not add new features to it, while all new platform work lands in modern .NET. Hiring gets harder every year, because fewer developers want to maintain System.Web code, and libraries you depend on drop support one by one.
There is also a hosting argument. A Framework app needs Windows Server and IIS. A modern .NET app can run on Linux containers, on smaller instances, and in the cloud without a Windows licence in the bill. For a company paying for a hosted Windows server in a Lahore data centre, that is a real conversation, though it should never be the only reason to migrate.
The honest reasons to move are support, security patching, performance headroom and the ability to hire and keep developers. If none of those hurts yet, you can schedule the work rather than rush it.
Rewrite, in-place upgrade or staged replacement
Three approaches cover nearly every project. The right one depends on how much of the code is web-layer specific.
Approach | Best for | Main risk | Disruption |
|---|---|---|---|
In-place upgrade | Small apps, mostly libraries and Web API | Hidden System.Web dependencies | Short freeze, one cutover |
Staged replacement | Large apps with many modules | Two codebases for a while | Low, route by route |
Full rewrite | Web Forms apps with tangled code-behind | Scope growth and lost business rules | High until launch |
Lift and shift only | Apps you cannot touch yet | Postpones the real problem | None now, more later |
A staged path from Framework to modern .NET
This is the order we follow on migration work. Skipping the early steps is how projects stall at ninety per cent.
- Inventory the applicationList projects, NuGet packages, target frameworks, third-party controls, scheduled jobs, Windows services and anything that reads from the registry, the GAC or local disk paths.
- Run the compatibility analysisUse Microsoft's upgrade and portability tooling to flag unsupported APIs. Treat the report as a map of effort, not a pass or fail grade, and check the tool's current status before relying on it.
- Move shared libraries firstRetarget business logic, data access and helpers to .NET Standard or a current .NET version. The old web app can keep referencing them, which proves nothing broke.
- Stand up the new web layer beside the old oneBuild an ASP.NET Core app and route selected URLs to it through a reverse proxy or a gateway, so each module moves when it is ready.
- Replace cross-cutting piecesAuthentication, session state, configuration, logging and dependency injection all work differently. Agree the new pattern once, then reuse it.
- Test, cut over, keep a rollbackRun parallel traffic where you can, compare outputs, then switch module by module. Keep the old route alive until the new one has survived a real billing cycle.
The blockers that surprise people
System.Web is the big one. HttpContext.Current, HttpModules, Global.asax events and the old page lifecycle do not exist in ASP.NET Core. Code that reaches into them from deep inside business classes is the main source of hidden work, because it only shows up when you compile against the new runtime.
WCF server services have no direct equivalent. If other systems call your SOAP endpoints, such as a bank integration or a government portal feed, you either keep them running under CoreWCF, wrap them with a new API, or negotiate a change with the other side. The same goes for Web Forms, which is not supported on modern .NET. Those pages need either a rewrite or a gradual move to Razor Pages, MVC or Blazor. Our service page on ASP.NET Web Forms modernization covers that path in detail.
Old Entity Framework 6 code usually runs on modern .NET, so you can move first and switch to EF Core later, or never. Crystal Reports, ActiveX controls and commercial UI suites with no current version are the other classic traps. Find them in week one.
Pre-migration readiness checks
Tick these before anyone writes a line of new code.
- Source control you trustEverything builds from the repository on a clean machine, not only on the one developer's laptop.
- Some automated testsEven a thin set of tests around billing, stock or approval rules gives you a way to prove behaviour did not change.
- A staging environmentA copy of the live setup, with a masked copy of real data, so cutovers are rehearsed.
- Known integrationsPayment gateways, SMS providers, courier APIs, accounting exports and scheduled imports are written down with owners.
- Logging and monitoringYou can see errors in production now, so you can compare after the move.
- A named decision makerSomeone can say yes or no on scope trade-offs without a committee meeting.
Pakistan-specific points to plan for
Many local systems were built by a previous vendor who has moved on, with no documentation and the database as the only source of truth. In that case, spend the first week reading stored procedures and scheduled jobs, because the real business rules often live there and not in the C# code.
Payment and courier integrations deserve their own test plan. Gateways and logistics APIs used by Pakistani stores change their endpoints and certificates with little notice, and a quiet failure during cutover costs orders. Our notes on custom payment gateway plugins for Pakistani stores show how to isolate that code behind one interface.
Hosting is the last point. If you are moving off a Windows server you rent locally, decide early whether the target is a Linux VPS, a container host or a cloud platform, because that choice affects deployment scripts, file paths and anything that touched the C: drive. For cloud targets, see our work on Azure and ASP.NET cloud solutions.
Common mistakes in .NET migrations
Most failed migrations fail for process reasons, not technical ones.
Starting with a big-bang rewrite
Business rules get lost, the old system keeps changing, and the new one never catches up.
Trusting the converter blindly
Tools get you compiling. They do not make the result idiomatic, secure or fast.
Ignoring session and auth
Users logged out during cutover is the fastest way to lose trust internally.
No performance baseline
Without before numbers, you cannot say whether the new app is faster.
Freezing features for a year
Business teams stop waiting. Plan to ship fixes in the old app while the move continues.
Forgetting the database
Schema changes during migration double the risk. Keep the schema stable until the cutover is done.
Testing and cutover without drama
Most migration pain arrives in the last week, not the first. The code compiles, the pages render, and then someone notices that rounding differs on an invoice, a date lands a day off because of a time zone default, or a report that ran in seconds now crawls. None of this is mysterious. It comes from small behaviour differences between runtimes, and the only reliable defence is comparing outputs before users do.
Our habit is to pick a handful of high-value flows, such as creating an invoice, approving a leave request or closing a day's cash, and run the same inputs through the old and the new system. Differences get investigated one at a time. Pay attention to culture and encoding settings too, since Urdu text, Pakistani date formats and currency display are classic places for quiet changes. Then plan the cutover for a quiet window, keep the old app deployable for at least one full business cycle, and agree in advance what result triggers a rollback. A rollback you never rehearsed is a hope, not a plan.
Choosing the target runtime and hosting
Once you commit to moving, pick a current long-term support release of .NET as the target and avoid chasing the newest preview. Support windows differ between releases, so check Microsoft's published lifecycle pages when you plan, and put a yearly upgrade slot in the calendar. Teams that treat later upgrades as routine rarely face another big migration.
Decide the hosting target early, because it changes deployment scripts and file handling. IIS on Windows remains a valid home for ASP.NET Core, and many companies keep it for a first phase to reduce change. Linux containers offer cheaper instances and cleaner deployments but need operations skills your team may not have yet. There is no prize for moving everything at once. A modest first cutover on familiar hosting, followed by a hosting change later, carries less risk than doing both in one weekend.

Junaid's take
In my experience, the companies that regret a migration usually tried to do three things at once: change the runtime, redesign the interface and clean the database. Pick one. Move the runtime first, because it removes the support risk, and let the redesign follow on stable ground.
If your application is mostly libraries and an API, I would upgrade it in place and finish within a short project. If it is a large Web Forms system that the business depends on daily, I would not promise a clean date at all until the inventory is done. I would run the old and new apps side by side and retire pages as they are replaced.
Before you hire anyone, ask them how they would roll back on day two of cutover. A good answer is concrete. If you want a second opinion on your own code, read about our ASP.NET development services or send us the project details and we will tell you which of the approaches above fits.

