.NET Modernization Tools: What They Do and Where They Stop
The main .NET migration tools — Microsoft's .NET Upgrade Assistant, the underlying try-convert engine, and API compatibility analyzers — automate the mechanical parts of a move: converting project files to the modern SDK format, retargeting frameworks, updating package references, and flagging APIs that are unavailable or behave differently. They genuinely save time on portable code. What they cannot do is the architectural work: rebuilding Web Forms, replacing server-side WCF, untangling logic from the UI, or deciding service boundaries. AI assistance extends how far the mechanical help reaches — drafting conversions and tests — but every output is reviewed by an engineer and proven by parity. Tools accelerate the migration; they do not replace the judgment it requires.
Five parts in, a phrase has kept recurring: tools handle the mechanical parts; the hard parts are rebuilt by hand. That is true, but it is also a cop-out unless someone draws the line precisely. This part does — because the most common .NET migration mistake after “rewrite it all at once” is trusting a tool to do work it cannot do, and discovering the gap halfway through.
The headline tool is Microsoft’s .NET Upgrade Assistant. Around it sit the conversion engine it builds on (try-convert), the API compatibility analyzers, and a growing layer of AI assistance. Each is genuinely useful inside its lane and quietly dangerous outside it. The job here is to map the lanes.
What the tools genuinely do well
The mechanical work of a platform move is real, voluminous, and tedious — and it is exactly what tooling is good at:
- Project-file conversion. The .NET Upgrade Assistant converts old-style project files to the modern SDK-style format, which is a prerequisite for everything else and miserable to do by hand across a large solution.
- Retargeting and multi-targeting. It updates the target framework and helps set up the multi-targeting (
net48plus a modern target) that Part 2 leaned on for shared libraries. - Package reference updates. It maps and updates NuGet references toward modern-.NET-compatible versions and flags packages with no modern equivalent.
- Known code fix-ups. It applies a catalog of mechanical source changes for patterns that have a clean, deterministic equivalent.
- Compatibility analysis. The API analyzers scan for calls that are unavailable on modern .NET or that compile but behave differently — the second category being the more dangerous one, because it fails silently.
For a codebase that is mostly portable libraries with a thin surface, this tooling can take you most of the way in days rather than weeks. That is a real win, and you should use it.
The pieces, and which job each one has
It helps to keep the tools distinct, because they are often spoken of as one and they do different jobs:
- The .NET Upgrade Assistant is the orchestrator you drive — a CLI and Visual Studio extension that walks a solution project by project, applies the conversions it can, and reports what it cannot. It is the front door.
- try-convert is the lower-level engine that performs the project-file conversion the Assistant builds on. You rarely call it directly now, but it is the thing actually rewriting your
.csproj/.vbprojinto SDK style. - The platform compatibility analyzers are the diagnostic layer — Roslyn analyzers that flag, at build time, APIs that are missing on your target or that compile but behave differently on modern .NET.
The analyzers deserve special attention, because they catch the most dangerous category in any platform move: the API that still compiles but behaves differently. A missing API fails loudly and you fix it. An API whose default changed — a culture-sensitive format, a different exception on a malformed input, a subtly altered sort — compiles green and then misbehaves in production. The analyzers surface those before they reach the parity gate, which is exactly where you want to learn about them.
Where the tools stop — and why
The line is sharp, and it is the same line that ran through Parts 3 to 5: tools can transform code that has a deterministic equivalent; they cannot invent an architecture that does not exist.
- Web Forms. There is no target to convert to, so no tool converts it. The page model has to be rebuilt on Blazor/Razor Pages/MVC by a human who decides how it should work now.
- Server-side WCF and ASMX. Same story — the host has no modern equivalent, and choosing between gRPC, REST, and CoreWCF is a design decision about callers, not a mechanical transform.
- Logic fused into the UI or service code. A tool can move a file; it cannot decide that this block of
Page_Loadis actually a pricing rule that belongs in a domain library. That extraction is judgment. - Service boundaries and decomposition. Where a monolith should split (Part 7) is a question about the business domain. No analyzer answers it.
A migration tool’s output is a punch list, not a finished migration. It tells you, quickly and accurately, what is mechanical and what is not — and the “what is not” pile is the actual project. Mistaking a green run of the Upgrade Assistant for “we’re nearly done” is how teams discover the WebForms-and-WCF mountain after the budget was set against the foothills.
Where AI changes the line — and where it does not
AI assistance is the newest entry, and it genuinely moves the boundary of what counts as “mechanical.” A model can draft a Blazor component from a Web Forms page, propose how to re-home a tangle of logic into a library, translate VB.NET to C#, and generate candidate tests — faster, and across messier code, than the older rule-based converters.
But it moves the boundary; it does not erase it. AI is confidently wrong about exactly the things that matter most in a business-critical migration: the undocumented edge case, the off-by-one in a financial calculation, the special path for one customer type. An unreviewed AI conversion that looks right and is subtly wrong is more dangerous than no conversion at all, because it passes the eyeball test and fails in production.
So the discipline is non-negotiable and it is the heart of how we use AI at all: AI is an accelerator inside a human-in-the-loop, parity-gated process. Every AI-drafted change is reviewed by an engineer who owns it, and every change — AI-drafted or hand-written — is proven equivalent by parity validation before it carries live traffic. AI is how we go faster on the mechanical and semi-mechanical work; it is never what decides whether a slice is correct. That judgment stays with people, and the parity gate stays in front of production.
How tools fit the method
Placed correctly, the tooling slots into the series’ loop without changing its shape:
- During assessment (Part 2), run the compatibility analyzers and the Upgrade Assistant’s analysis pass to produce the dependency map and the “ports cleanly vs must be rebuilt” inventory.
- During the shared-library work, use the Upgrade Assistant to convert and multi-target the portable code — this is its sweet spot.
- During each slice rebuild, use AI assistance to draft the conversion and the tests, then review and harden them.
- At the parity gate, the tools step back entirely. Equivalence is proven by comparing behavior, not by trusting that the conversion was faithful.
Tools compress the timeline; the method controls the risk. You need both.
Neither dismiss the tools nor over-trust them
It would be just as wrong to dismiss the tools as to over-trust them. For portable code the Upgrade Assistant saves real, unglamorous effort, and AI meaningfully speeds the slice rebuilds — refusing to use them is its own kind of waste. The failure is not using tools; it is letting a tool’s confidence stand in for a human’s verification on code the business depends on. Use everything that accelerates the mechanical work, and put the parity gate between all of it and production.
Where this leads
Tools and method get a Framework app onto modern .NET. But “on modern .NET” is not automatically “well-architected” — a lifted-and-shifted monolith is still a monolith. Part 7, .NET Monolith to Microservices, takes on the architecture question the platform move surfaces: when a modern .NET monolith should be decomposed into services, and — just as important — when it should be left alone.
Frequently asked questions
- What does the .NET Upgrade Assistant actually do?
- The .NET Upgrade Assistant is a Microsoft tool (a CLI and a Visual Studio extension) that automates the mechanical steps of moving a project toward modern .NET: converting old-style project files to the SDK format, retargeting the framework, updating NuGet package references, and applying known code fix-ups. It guides you project by project and flags what it cannot handle. It is genuinely useful for portable code, but it does not rebuild Web Forms, replace WCF, or re-architect anything — those it reports and leaves to you.
- Can a tool migrate .NET Framework to .NET 8 automatically?
- Only the mechanical portion. Tools convert project formats, retarget, update packages, and surface incompatible APIs automatically, which removes a lot of tedious work. But the parts that make a Framework migration hard — Web Forms with no forward port, server-side WCF, business logic fused into the UI, choosing where services should split — require human design decisions. Treat the tools as a fast first pass that handles the boilerplate and produces a punch list, not as an end-to-end migrator.
- Does AI replace these migration tools?
- No — it extends them, under supervision. AI can draft code conversions, propose how to re-home logic, and generate candidate tests faster than the older rule-based tools, which pushes the boundary of what is "mechanical." But AI output is not trustworthy on its own for business-critical code: it can be confidently wrong about exactly the undocumented edge cases that matter. So AI is used as an accelerator inside a human-in-the-loop, parity-gated process — every change reviewed by an engineer and proven equivalent before it ships.