Pre-Migration Checklist for Moving from .NET Framework to .NET

· · .NET, .NET Framework, C#, Modernization, Windows Development, Migration

Download the Excel checklist with Japanese and English sheets

Change TargetFramework in the .csproj to net10.0, update a few NuGet packages, and once the build passes, you are done.

…If that were the migration, life would be pretty peaceful. In reality, it usually is not.

.NET Framework codebases are full of dormant assumptions you normally never think about: System.Web, WCF, Web Forms, old packages.config files, web.config.install.xdt, native DLLs, COM / ActiveX, third-party controls that only work at design time, implicit x86 assumptions, designer-dependent ResX, old serializers, and more.

So what really matters in a .NET Framework to .NET migration is the inventory work before you start implementing. If you can break the issues down before starting, the migration stops being “a big gamble” and becomes “a list of items to knock down in order.”

This article summarizes what you should verify before migrating an existing .NET Framework 4.x line-of-business application to current .NET. The main targets are around here:

  • Class libraries
  • Console applications
  • Windows services
  • WinForms / WPF
  • ASP.NET Framework (MVC / Web API / Web Forms)
  • Applications that use WCF
  • Applications that use EF6

This was written as of 2026-03-15. Support windows and official tooling recommendations change, so if you are reading this much later, check the official information as well.

1. The Conclusion First

First, the conclusions that are hard to get wrong.

  • Clean up the .NET Framework side before migrating. Microsoft’s official guide also recommends upgrading to .NET Framework 4.7.2 or later before porting, and completing PackageReference conversion, SDK-style conversion, and dependency updates first.
  • Difficulty is determined by app model, not by code volume. Class libraries and console apps are relatively light; ASP.NET Framework, Web Forms, WCF servers, and WF tend to be heavy.
  • WinForms / WPF can migrate to .NET but remain Windows-only. Misunderstand this and you step on the classic landmine of migrating only to find the app will not run in a Linux container.
  • ASP.NET Framework → ASP.NET Core is effectively an architecture migration. Small apps can sometimes go in one shot, but for large production systems it is safer to plan on an incremental migration.
  • WCF and EF6 can sometimes be decoupled from the runtime migration. WCF clients have supported packages for .NET, and EF6 can be migrated to EF Core separately after the move to modern .NET.
  • On the other hand, AppDomain creation, .NET Remoting, CAS, COM+, Workflow Foundation, and BinaryFormatter dependencies are red lights. Find them early, or the effort explodes later.
  • packages.config / install.ps1 / XDT / content assets / native DLLs / COM / ActiveX / x86 assumptions tend to fail at runtime or design time even when the build passes, so flush them out before starting.
  • As of 2026-03, .NET 10 is the LTS. For new migrations, it is natural to target the current LTS as the landing point.
  • A migration without tests, measurements, and a rollback plan is dangerous. Migration is less an implementation task than a job of making assumptions visible, one at a time.

2. First Decide Whether You Should Migrate Right Now at All

The first thing to decide is not “how to migrate” but whether this app really should be migrated right now.

Leave this vague and you tend to end up with a migration that is technically correct but too heavy for the business — or the opposite: postponing far too long when migration is clearly the right call.

2.1 Staying on .NET Framework Is a Perfectly Valid Decision

.NET Framework 4.8.1 continues to be supported as long as it runs on a supported Windows. In other words, it is not as simple as “if you do not move everything to modern .NET right now, you are immediately at risk.”

However, staying has clear constraints.

  • You cannot escape being Windows-only
  • You keep carrying ASP.NET Web Forms and old server stacks
  • It is harder to benefit from new .NET performance improvements, language features, and the ecosystem
  • You drift away from the modern assumptions of cloud, containers, and CI/CD

Conversely, if dependencies like the following are strong, it is rational to consolidate on .NET Framework 4.8.1 for stable operation for now, while planning the replacement on a separate track.

  • A large stock of Web Forms screens
  • Strict WCF server compatibility must be preserved
  • Deep Workflow Foundation or COM+ dependencies
  • Third-party design-time components do not support modern .NET
  • The business does not allow major specification changes

2.2 What Changes with Each Option

Option What gets better What remains / what you give up Good fit
Stay on .NET Framework 4.8.1 Easy to keep existing assets intact and operate stably Windows-only, old app models, limits on modernization Strong legacy dependencies; the business priority is stable operations for now
Migrate to modern .NET but stay on Windows Runtime and toolchain modernized. Big gains in performance, developer experience, SDK style Windows API dependencies remain. Not cross-platform WinForms / WPF, Windows services, business apps using Windows APIs
Migrate to modern .NET with Linux / containers / cloud in future scope More freedom in deployment targets. Easier to modernize the operations model Windows-only APIs and app models must be peeled off first You want to shift the server side toward the cloud and refresh infrastructure too

What matters is deciding not whether you want to migrate but where you want to land after the migration — first.

3. Four Policies to Decide Up Front

3.1 The Target .NET Version

At the time of writing, under Microsoft’s support policy, .NET 10 is the LTS. Meanwhile, .NET 8 LTS and .NET 9 STS are both scheduled to reach end of support on 2026-11-10.

So if you are now starting a fresh migration off .NET Framework, barring exceptional circumstances, landing on the current LTS is the natural choice.

The practical reasoning here is simple.

  • For a small migration you want done quickly, land directly on the current LTS
  • For a core system intended for long-term operation, still treat the current LTS as the baseline
  • “We want the previous LTS because of an existing library” is a legitimate reason, but judge it by checking the actual maintenance end date

3.2 Stay Windows-Only, or Aim for Cross-Platform Later?

This decision dramatically changes which issues you need to look at.

  • If you stay Windows-only, you can take the pragmatic route of modernizing the runtime first, using WPF / WinForms and the Windows Compatibility Pack.
  • If you are aiming for Linux / containerization later, you need to inventory Windows-bound APIs early: System.Drawing.Common, the registry, WMI, EventLog, Windows services, COM, Office Interop, and so on.

Start migrating without deciding this, and midway through, the conversation gets twisted: “Was Windows-only fine after all?” “No wait, we wanted to run in containers.”

3.3 One Shot or Incremental?

There are broadly three migration shapes.

  • Near in-place, all-at-once migration
  • Side-by-side migration running old and new in parallel
  • Incremental migration, moving over route by route or library by library

Especially for ASP.NET Framework apps, Microsoft’s guidance explicitly recommends incremental migration. If you cannot stop production, have many features, and have many surrounding dependencies, it is less strained to design for incremental migration from the start.

3.4 What to Exclude from This Migration

Migrations tend to fail because too much gets piled on.

For example, doing all of these at once tends to get heavy:

  • .NET Framework → .NET
  • ASP.NET Framework → ASP.NET Core
  • EF6 → EF Core
  • Windows servers → Linux containers
  • Changing the authentication infrastructure
  • Changing the logging / monitoring infrastructure
  • Migrating the database

Of course, all of them may eventually be necessary. But whether they must be done at the same time is a separate question.

In reality, separating things like this works better:

  1. First modernize the runtime and project structure
  2. Then move the app model
  3. Finally update the ORM, authentication, cloud, and monitoring

4. The Foundation to Prepare Before Starting

Microsoft’s pre-porting guide is quite practical. In essence: before migrating, bring your current .NET Framework projects up to a modern entry point.

4.1 Upgrade to .NET Framework 4.7.2 or Later

The official guide recommends targeting .NET Framework 4.7.2 or later before porting. The reason is that even when .NET Standard does not carry an existing API as is, it becomes easier to move toward newer API alternatives.

In practice, it is clearer to use 4.8.1 as the baseline if possible.

  • Straightforward from a support standpoint
  • Easy to treat as the final stable point on the .NET Framework side
  • Makes the policy of “first clean up on the current Framework side” easy to establish

What changes if you do this first

  • Handling of .NET Standard 2.0 shared libraries stabilizes more easily
  • Noise originating from the old runtime is reduced up front
  • It becomes easier to tell whether a compatibility issue is caused by “the Framework being old” or by “the move to modern .NET”

4.2 Move to PackageReference

The pre-porting guide recommends converting references to the PackageReference format. Doing this first significantly improves visibility into dependency management.

What changes with PackageReference

  • Package references are consolidated into the csproj
  • Transitive dependencies become easier to see
  • The restore assumptions line up with the modern .NET side
  • Better compatibility with the CLI / CI

However, there are landmines here.

Typical landmines

The official NuGet documentation explicitly lists these constraints for migrating from packages.config to PackageReference:

  • Visual Studio’s built-in migration cannot be used for ASP.NET projects
  • Packages that depend on install.ps1 / uninstall.ps1 may not work as expected
  • Assets in the content folder may be ignored
  • XDT transforms such as web.config.install.xdt are not applied
  • Packages with old assembly layouts directly under lib may not resolve well

In other words, do not think of it as merely changing the package format. Classic ASP.NET in particular had a strong culture of rewriting web.config at NuGet package install time, so implicit assumptions surface easily during migration.

4.3 Move to SDK-Style Projects

The pre-porting guide also recommends converting to the SDK-style project format.

This pays off substantially.

What changes with SDK style

  • The csproj becomes dramatically more concise
  • Plays well with PackageReference
  • Multi-targeting becomes easy
  • Easier to center CI/CD on dotnet build / dotnet test / dotnet publish
  • The configuration approaches the modern .NET side, reducing the diff in the later phase

Put the other way around: jumping straight to modern .NET with old csproj files and old NuGet management produces too large a diff.

4.4 Update Dependencies First

This too follows the official guide: move dependencies to the latest available versions, and where possible to .NET Standard-compatible versions.

Why do this first

  • You find out early whether “this package works on modern .NET”
  • Prevents old dependencies from becoming noise
  • Makes it easier to convert shared libraries to netstandard2.0
  • Lets the later migration work focus on “porting the code”

4.5 Check the Assumptions of the Official Tooling Too

As of 2026-03, the center of gravity of Microsoft’s guidance has shifted toward GitHub Copilot app modernization. Rather than assuming only the traditional migration assistant tools, it matches practice better to view it as an end-to-end support flow covering assessment, planning, code fixes, and validation.

However, the current documentation assumes Visual Studio 2026 or a supported Visual Studio 2022 line, GitHub Copilot, and C# code.

Why this check is needed

  • It changes what you can expect from the official tooling
  • You can align the team’s assumptions about IDEs / build agents / extensions
  • You can make the call to not over-rely on automation for VB.NET solutions

Codebases with VB.NET mixed in are not rare. So it is worth confirming, at the very start, “how far the latest official tooling will actually help.”

5. Estimating Difficulty per Project Type

Migration tends to be discussed as one lump — “.NET Framework to .NET” — but in reality each project type is a different game.

5.1 A Rough Sense of Difficulty

Type Difficulty Main issues
Class library Low to medium API compatibility, dependencies, target splitting
Console / batch / some Windows services Low to medium Distribution method, native dependencies, configuration
WinForms / WPF Medium Remains Windows-only; designer, third-party UI, BinaryFormatter surroundings
ASP.NET MVC / Web API Medium to high App model migration to ASP.NET Core, authentication, session, configuration, DI
ASP.NET Web Forms High Large gap in page model; assume UI layer replacement
WCF client Medium Package replacement, contracts, configuration
WCF server High CoreWCF, or redesign as gRPC / HTTP API
EF6 → EF Core done simultaneously High The ORM is a different beast; behavioral differences; migration history

5.2 For Class Libraries, the Key Is How You Cut the “Shared Boundary”

Class libraries are relatively easy to move. But only when the library is genuinely separated like a library.

Dependencies like the following raise the difficulty:

  • Touching System.Web
  • Reading HttpContext.Current directly
  • Exposing WPF / WinForms types in the public API
  • Leaning heavily on Windows APIs such as the registry, WMI, EventLog
  • Depending on AppDomain or Remoting

A useful framing: if you can extract pure business logic, it is light; if the library has swallowed the app model, it is heavy.

5.3 WinForms / WPF Migrate Easily, but Stay Windows-Only

WinForms and WPF can be migrated to .NET. However, both remain Windows-only frameworks.

Getting expectations wrong here is dangerous.

  • What improves
    • You get the modern .NET runtime, language, and SDK style
    • CI/CD and package management can be brought up to date
    • Some performance and maintainability improvements come along
  • What does not change
    • It is still Windows-only
    • Compatibility issues with UI controls and design-time components remain
    • ActiveX / COM / native DLL problems do not go away

Also, WinForms / WPF can require a BinaryFormatter impact review. Especially when custom types are involved in the clipboard, drag & drop, ResX, or design-time serialization, the issue tends to surface when you raise the target to .NET 9 or later.

5.4 ASP.NET Framework Is an “App Model Migration,” Not a “Runtime Migration”

Migrating from ASP.NET Framework to ASP.NET Core is explicitly described as non-trivial in Microsoft’s guidance. Not merely because API names change, but because the underlying architecture is different.

The differences tend to show up around here:

  • Hosting model
  • Middleware pipeline
  • Request processing model
  • Session / Cache
  • Authentication / Authorization
  • Configuration
  • Dependency Injection
  • Logging / Monitoring

For an ASP.NET Framework app, the things to check first are around here:

  • Which routes / endpoints can be moved first
  • Whether System.Web dependencies can be peeled out of shared libraries
  • How to align authentication / session / exception handling / logging
  • Whether to migrate incrementally without stopping production

For large apps in particular, it is more realistic to assume incremental migration from the start.

5.5 For Web Forms, Start with “Decomposing Responsibilities,” Not “Migrating Assets”

Web Forms is not the same app model as ASP.NET Core. So for estimation purposes, it is safer not to assume the screen assets can be carried over as is.

In practice, the usual entry point is this decomposition:

  • Separate screen logic from business logic
  • Break apart the responsibilities buried in Page / UserControl / ViewState
  • Move business logic and data access out into shared libraries
  • Rebuild the UI on a different model: Razor Pages / MVC / Blazor, etc.

In other words, for Web Forms projects, whether there is a responsibility-decomposition plan matters more than the runtime migration itself.

5.6 Treat WCF Clients and WCF Servers Separately

Do not lump these together.

WCF clients

The WCF Client has supported NuGet packages for modern .NET. So if you only call WCF, the work can be lighter than it looks.

WCF servers

Hosting WCF services, on the other hand, is a different story. Microsoft’s guidance presents two broad modernization paths:

  • Use CoreWCF to preserve compatibility with existing clients
  • Move to modern RPC / HTTP-based stacks such as gRPC

Note that CoreWCF is a subset — it does not bring over all of WCF as is. It is suited to preserving compatibility with existing clients, but code changes and testing are a given.

6. Flush Out Technologies That Do Not Work on .NET, or Get Stuck Easily

This is something you absolutely want to do before starting. Microsoft maintains a list of technologies available on .NET Framework that are unavailable on .NET 6+.

6.1 Technologies That Tend to Be Red Lights

Technology Status on .NET How to think about it
AppDomain creation such as AppDomain.CreateDomain Unsupported Think of isolation via separate processes / containers / AssemblyLoadContext
.NET Remoting Unsupported Redesign around IPC, HTTP, gRPC, sockets, pipes
CAS / Security Transparency Unsupported as a security boundary Think in terms of OS / container / privilege separation
System.EnterpriseServices (COM+) Unsupported Isolate and replace COM+-based designs
Workflow Foundation Unsupported Estimate separately, including alternatives such as CoreWF
WCF server Not available as is in the box Choose CoreWCF or gRPC
BinaryFormatter On .NET 9+ the implementation always throws Migrate serializers; audit ResX / clipboard / drag & drop

6.2 AppDomain: “Some APIs Remain, but Creation Is a Different Matter”

The AppDomain area is a bit tricky. Some of the API surface remains on .NET, but the usage pattern of creating a new AppDomain for isolation is not supported.

So if you used AppDomains for the following purposes, a redesign is needed:

  • Plugin isolation
  • Unloading dynamically loaded code
  • Isolating partially trusted code
  • Temporary separation of execution environments

What you should look at before migrating is not just whether the word AppDomain appears, but what the AppDomain was being used for.

6.3 Remoting Is “Deeper Than It Looks”

Remoting itself, obviously — but asynchronous delegate calls like BeginInvoke() / EndInvoke() on delegates can also fall into the affected area. This is not Remoting per se, but it is unsupported on modern .NET, so it needs to be flushed out before migrating.

So when searching, it is safer to look at this set together:

  • System.Runtime.Remoting
  • MarshalByRefObject
  • RealProxy
  • BeginInvoke( / EndInvoke(

6.4 BinaryFormatter Suddenly Comes to the Fore Depending on the Target Version

The older the codebase, the more likely BinaryFormatter is being used “without awareness.”

  • Persisted data
  • Caches
  • Session storage
  • Plugin state
  • Clipboard / drag & drop
  • ResX
  • WinForms / WPF designer surroundings

On .NET 9 and later, BinaryFormatter’s implementation is not included in the runtime and the API always throws PlatformNotSupportedException. So this is not a “think about it later” item — it is an audit item the moment you decide the target version.

6.5 Search Terms to Grep for First

Before starting, just running searches over the whole solution with the following terms changes the picture considerably.

System.Web
HttpContext.Current
System.Runtime.Remoting
MarshalByRefObject
AppDomain
BinaryFormatter
ServiceHost
ChannelFactory
System.EnterpriseServices
Workflow
packages.config
web.config.install.xdt
install.ps1
DllImport
AxInterop
Microsoft.Office.Interop

Finding even one of these does not mean instant failure. It is a map for knowing which parts can migrate on the standard route and which become a separate track.

7. Decide How Much Windows-Only Dependency to Accept

A common misunderstanding in migrations is “once we are on .NET, we are cross-platform.” There is no such magic. If the app is deeply tied to Windows, it remains Windows-only after the migration, plainly.

7.1 Migrating While Staying Windows-Only Is Entirely Realistic

Microsoft provides the Windows Compatibility Pack, a way to use many Windows-oriented APIs — the registry, WMI, EventLog, Windows services, Directory Services, and so on — from modern .NET.

Its existence matters a lot in practice.

  • We want to move to modern .NET first
  • But we are not leaving Windows for now
  • So we want to accept the Windows API dependencies for the time being

For teams in that situation, it is a strong option.

The first goal of a migration does not have to be going cross-platform.

7.2 But Windows-Only APIs Are Also “Debt That Bites Later”

The Windows Compatibility Pack existing does not make everything safe.

  • You want to run in Linux containers
  • You want to run on Kubernetes
  • You want macOS / Linux developers running the same build
  • You want to reduce Windows VMs in the cloud someday

If you have goals like these, it is better to make the Windows API dependencies visible now.

7.3 System.Drawing.Common Is Especially Often Misunderstood

System.Drawing.Common is a Windows-only library on .NET 6 and later. If you have code using it for image processing or text rendering, you first need to decide which way to go.

  • Keep operating on Windows?
  • Or want it running on Linux / macOS in the future?

In the former case, leaving it as is for now can be fine. In the latter, a replacement — SkiaSharp, ImageSharp, etc. — needs to be in the migration plan from the start.

7.4 Typical Smells That Indicate Windows Lock-In

When references or APIs like the following are present, it is safer to estimate on the assumption of “migrating while staying Windows-only, at least at first.”

  • Microsoft.Win32.Registry
  • System.Management
  • System.Diagnostics.EventLog
  • System.ServiceProcess
  • System.DirectoryServices
  • System.Drawing
  • DllImport / P/Invoke
  • COM references
  • AxInterop.*
  • Microsoft.Office.Interop.*

8. How You Carve Out Shared Libraries Changes the Difficulty

For larger solutions, it is no exaggeration to say the success of the migration is determined by how you cut the shared libraries.

8.1 Classify First

Libraries are easiest to organize when split into three broad kinds.

  1. Pure business logic / domain logic
  2. Middle layers with some app model dependency
  3. Layers tightly coupled to UI / Web / Windows APIs

Of these, the first to migrate should be kind 1.

  • Calculations
  • Rule evaluation
  • DTOs / contracts
  • Domain services
  • Simple data transformations

If you can extract this cleanly, the difficulty drops sharply.

8.2 netstandard2.0 Is Still a Valid Bridge

Per Microsoft’s guidance, for a shared library that must also coexist with the .NET Framework side, the baseline is to consider .NET Standard 2.0 first.

Two points matter here.

  • .NET Framework does not support .NET Standard 2.1
  • If you want a shared library referenced from both old and new, 2.0 tends to be the practical answer

8.3 What Changes with netstandard2.0

Policy What changes Good fit Caveats
Convert to netstandard2.0 Easy to reference from both old and new Pure business logic, common contracts, utilities App-model-specific APIs cannot live here
Multi-target (e.g. net48;net10.0) Keep common code while holding per-environment differences Libraries with a few environment differences More conditional compilation and build management
Go straight to net10.0-only Cleanest in the long run New layers that do not need old/new coexistence Cannot be referenced from .NET Framework

8.4 Compatibility Mode Is Not a Cure-All

.NET Standard 2.0 has a compatibility mode that allows referencing .NET Framework libraries. However, this is not magic that makes everything work transparently.

For example, libraries that assume app-model-specific APIs like WPF are plainly difficult. In other words, even when you say “shared library,” it is important to narrow it down to the responsibilities that can truly be shared.

When incrementally migrating ASP.NET Framework, having shared libraries hang directly off HttpContext.Current or System.Web is quite painful.

The basic strategies at that point are one of these:

  • Push the System.Web dependency outside the interface
  • Change the code to receive HttpContext-derived information as DTOs
  • Use adapters during the transition period
  • If that still does not work, peel it off gradually with multi-targeting

8.6 Raise Libraries Leaf-First

The ASP.NET incremental migration guide explicitly says to upgrade supporting libraries postorder depth-first — that is, from the leaves up.

This is quite effective for general solutions too, not just web.

  • Because dependencies are upgraded first, the upper layers become easier to see through
  • Compatibility issues are easier to localize
  • Testing per library becomes easier

9. Take Inventory of NuGet / External Dependencies / Third-Party Components

Do this sloppily and you suffer the worst pain in the second half of the migration.

9.1 Dependencies Are Easier to Organize in 4 Categories

  1. Public NuGet packages
  2. In-house private packages / internal libraries
  3. Local DLL references
  4. COM / ActiveX / native DLLs / SDKs

Looking only at category 1 is not enough. The really dangerous ones are 3 and 4.

9.2 What to Verify for Each Dependency

For each dependency, verify at least this much:

  • Does it target modern .NET?
  • Does it support PackageReference?
  • Is it fine with SDK-style projects?
  • Any x86 / x64 / ARM64 constraints?
  • Does it depend on design-time tooling or Visual Studio extensions?
  • Does it assume install scripts / config transforms?
  • Is it still supported?

9.3 Estimate Third-Party UI / Reporting / Design-Time Components Separately

For WinForms / WPF / ASP.NET migrations, this area matters a lot.

  • Grids
  • Reporting engines
  • PDF output components
  • Charting components
  • Designer-integrated UI libraries
  • ActiveX wrappers

These involve design-time support, not just the runtime. If your migration estimate only checks “does it compile,” you will plainly miss these.

9.4 Always Check Native DLLs and Bitness

Even if things seemed to run as AnyCPU in the .NET Framework era, in reality they may depend on things like:

  • COM fixed to x86
  • 32-bit-only ActiveX
  • A specific version of the VC++ Runtime
  • Signed native DLLs

These are not problems that suddenly sprouted with the move to modern .NET — constraints that were always there simply surface. Which is exactly why it is worth making them visible before the migration.

10. Treat EF6, Serializers, and the Data Layer as Separate Problems

The runtime migration and the redesign of data access and serialization work out better when treated as separate problems wherever possible.

10.1 EF6 → EF Core Is Not a Direct Upgrade

Microsoft’s EF guidance also states that EF Core is a total rewrite of EF6 and there is no direct upgrade path.

So for apps using EF6, this order is realistic:

  1. First move to modern .NET
  2. Keep EF6 if needed and run the app
  3. Then migrate to EF Core as a separate project

Do not combine the runtime migration with the ORM migration. That alone lowers the difficulty considerably.

10.2 What Changes if You Keep EF6

  • Upsides
    • The data access layer diff can be deferred
    • You can focus on migrating business logic and the app model
    • “EF Core behavioral differences” do not get mixed in
  • Caveats
    • For new development, EF Core is the main line
    • EF6 Designer / EDMX usage patterns have separate constraints

10.3 For EDMX-Based EF6, Look All the Way to “Design Time”

The EF6 documentation states that the EF Designer is not directly supported in .NET / .NET Standard projects or SDK-style .NET Framework projects.

For EDMX-based apps, you need to consider these three points separately:

  • Does it run at runtime?
  • Can the Designer be used?
  • How will the generated code be handled?

If you use EDMX heavily, it is safer to put this in the estimate from the start.

10.4 BinaryFormatter and Custom Serialization Easily Become “Hidden Dependencies”

Serializers are easy to miss with code search alone.

  • Persistence formats
  • Messaging
  • Caches
  • Old WCF / SOAP contracts
  • ResX
  • Clipboard / drag & drop

This area also involves data compatibility. That is, you need to verify not just “does it build” but can it still read the old data.

11. Include Configuration, Distribution, Operations, and CI/CD in the Migration Scope

The migration target is not just source code.

11.1 Configuration Files

On the .NET Framework side, quite a lot can be riding in app.config / web.config.

  • Connection strings
  • Custom config sections
  • WCF endpoint configuration
  • Binding redirects
  • Diagnostics
  • Various ASP.NET settings
  • The results of transforms applied at package install time

On the modern .NET side, how configuration is held and loaded changes in places. So “configuration files later” is dangerous.

The first thing to do is an inventory of the configuration.

  • What lives in the configuration files
  • Which entries are required at app startup
  • Which are per-environment differences
  • Which were auto-injected by NuGet or installers

11.2 Distribution Method

Look at the distribution shape before starting too.

  • Hosted under IIS?
  • A Windows service?
  • A Scheduled Task?
  • ClickOnce / MSI / a custom installer?
  • On-premises servers assumed?
  • Is self-contained or framework-dependent the better fit?

Even if the executable itself migrates, you get stuck at the end if the distribution and startup machinery still assumes the old world.

11.3 Logging, Monitoring, and Operational Procedures

The operations side is easy to overlook as well.

  • Is the Windows Event Log assumed?
  • Are Performance Counters being watched?
  • WMI-based monitoring?
  • Are service accounts and permissions fixed?
  • Do logs assume local file output?

“The code runs after the migration, but operations cannot function” happens, plainly.

11.4 CI/CD and Build Agents

Before migrating, also check:

  • Can the required .NET SDK be installed on the build agents?
  • What to do with pipelines that assume nuget.exe / msbuild.exe
  • Will you move to the dotnet CLI?
  • How to update the test, coverage, and publish jobs
  • Are in-house templates or reusable pipelines assuming the old formats?

“It works on my machine but CI dies” is a migration classic.

12. A Realistic Way to Run the Migration

Given everything above, a realistic approach usually settles into roughly this shape.

12.1 First, Put the Current Framework Side in Order

  1. Move to .NET Framework 4.7.2 or later, ideally 4.8.1
  2. Upgrade dependencies
  3. Review packages.config
  4. Move to PackageReference and SDK style where possible
  5. Confirm the current app genuinely works in that state

Just doing this reduces the diff in the later phase considerably.

12.2 Rescue the Shared Libraries First

Next, move business logic and common contracts toward netstandard2.0 or multi-targeting. The order of upgrading is, as a rule, leaf-first.

12.3 For the Application Itself, Vary the Strategy per App Model

  • Class libraries / console / some services Relatively straightforward
  • WinForms / WPF Modernize while staying Windows-only
  • ASP.NET MVC / Web API All at once if small; incremental if heavy
  • Web Forms Assume screen replacement; move shared logic out first
  • WCF servers Decide first: stay with CoreWCF or redesign with gRPC

12.4 Stick to “Not Everything at Once”

The combinations to particularly avoid:

  • Runtime migration + full ORM swap
  • Runtime migration + authentication infrastructure change
  • Runtime migration + full cloud migration
  • Runtime migration + monitoring infrastructure change
  • Runtime migration + UI framework refresh

Even if all of them are needed, not stacking them in the same sprint usually works out better.

12.5 Take Tests and Baselines Before Moving

At minimum, you want this much in place before moving:

  • Unit tests
  • Integration tests for the main business flows
  • Snapshot-style verification of representative screens / APIs
  • A performance baseline
  • A way to check the main logs
  • A rollback procedure

Proceeding in a state where you cannot identify “what broke” after the migration is quite dangerous.

13. Pre-Start Checklist

Here it is in a form you can paste straight into your project management tool.

13.1 Policy

  • You can state in one sentence why you are migrating
  • The landing point is decided: Windows-only modern .NET or future cross-platform
  • The target .NET version is decided
  • What is excluded from this scope (EF Core conversion, auth refresh, full cloud migration, etc.) is decided

13.2 Preparing the Current .NET Framework Side

  • Moved to .NET Framework 4.7.2 or later, ideally 4.8.1
  • Upgraded dependencies toward the latest
  • Checked for packages.config
  • Verified feasibility of converting to PackageReference
  • Verified feasibility of converting to SDK style
  • The current app builds, starts, and passes tests in that state

13.3 App Types and Technology Choices

  • Split difficulty by type: class library / desktop / web / WCF, etc.
  • Understood that WinForms / WPF remain Windows-only
  • Understood that ASP.NET Framework means an app model migration to ASP.NET Core
  • Included Web Forms UI layer replacement in the estimate
  • Evaluated WCF clients and servers separately

13.4 Unsupported Technologies / APIs Requiring Attention

  • Flushed out AppDomain dependencies
  • Flushed out Remoting / MarshalByRefObject / BeginInvoke / EndInvoke
  • Flushed out CAS / Security Transparency / COM+ / WF
  • Flushed out BinaryFormatter dependencies
  • Flushed out System.Web dependencies

13.5 Windows-Only Dependencies

  • Flushed out use of the registry, WMI, EventLog, Windows services, Directory Services
  • Flushed out use of System.Drawing.Common
  • Flushed out COM / ActiveX / Office Interop / P/Invoke / native DLLs
  • Verified x86 / x64 / ARM64 constraints

13.6 Shared Libraries and Data Access

  • Classified shared libraries into business logic / app-model-coupled layers
  • Flushed out what can be converted to netstandard2.0
  • Flushed out libraries that need multi-targeting
  • Decided whether the runtime can move first while keeping EF6
  • Verified EDMX / Designer dependencies

13.7 Operations and Build

  • Took inventory of the configuration files
  • Verified the distribution method (IIS / service / MSI / ClickOnce, etc.)
  • Verified logging / monitoring / permissions / execution account assumptions
  • Verified whether CI/CD and build agents need updating
  • Created a rollback procedure

14. Summary

What matters in migrating from .NET Framework to .NET is not “which command to migrate with” but seeing, before you start, what carries over as is and what is a separate problem.

Narrowed to the essentials, it is these six points:

  • Clean up the .NET Framework side before migrating
  • Split difficulty by app model
  • Flush out the unusable technologies first
  • Decide how much Windows-only dependency to accept
  • Decide how to carve out the shared libraries
  • Do not pile on ORM, authentication, and cloud migrations at the same time

The accuracy of the estimate changes dramatically in the first week of a migration. Put another way, if you can sort out the issues in that week, the second half can be steered fairly close to ordinary development.

“Let’s just try changing it to net10.0” is not bad as exploration. But as a production migration, there are things to look at before that. What this article organized is exactly that.

15. References

Recent articles sharing the same tags. Deepen your understanding with closely related topics.

These topic pages place the article in a broader service and decision context.

This article connects naturally to the following service pages.

Technical Consulting & Design Review

If you want to sort out the migration scope, how to slice an incremental migration, and how much Windows-only dependency to accept before starting, this topic works well as a technical consulting / design review engagement.

Author Profile

Profile page for the article author.

Go Komura

Representative of KomuraSoft LLC

Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.

Back to the Blog