← Back to Tutorials Chapter 12

Migrations

Moving from the classic .NET Framework to .NET Core (modern .NET) requires careful planning. This chapter covers migration strategies, tooling, breaking changes, and best practices for large codebases.

Upgrading from .NET Framework

Modern .NET (5, 6, 7, 8+) is the successor to both .NET Core and .NET Framework. The recommended path is:

  1. Run the .NET Portability Analyzer to assess compatibility.
  2. Convert packages.config to PackageReference.
  3. Retarget the project to a compatible .NET Standard version (2.0 is widely compatible).
  4. Upgrade to the latest .NET SDK and recompile.

project.json to csproj Conversion

Early .NET Core used project.json; the SDK later returned to the .csproj format. If you still have project.json:

dotnet migrate                     # Automated migration tool
# Or manually create a .csproj:
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>
</Project>
The dotnet migrate command was deprecated after .NET Core 3.0. For newer projects, create a new SDK-style project and port your code manually.

API Compatibility Analyzer

The API Compatibility Analyzer (Microsoft.DotNet.ApiCompat) helps identify APIs that are not available on your target platform. It runs as an MSBuild task:

<PackageReference Include="Microsoft.DotNet.ApiCompat" Version="8.0.0" />

Run dotnet build and review any compatibility warnings.

Breaking Changes

Several technologies from .NET Framework are not available in modern .NET:

.NET Core migration path

Porting Analyzer Tool

The dotnet-apiport tool (now integrated into Visual Studio) scans your assemblies and generates a detailed report of API usage and compatibility.

dotnet tool install -g dotnet-apiport
dotnet apiport analyze -f MyApp.exe -t net8.0 -o report.html

.NET Standard Compatibility

.NET Standard 2.0 is the bridge between .NET Framework and modern .NET. Libraries targeting .NET Standard 2.0 can be consumed by both ecosystems.

.NET StandardSupported by
2.0.NET Framework 4.6.1+, .NET Core 2.0+, Unity 2018.1+
2.1.NET Core 3.0+, .NET 5+ (not supported by .NET Framework)
If you need to support .NET Framework consumers, target netstandard2.0. For new libraries, target net8.0 (or later) to access the latest APIs.

Tips for Large Codebases

Dual-Targeting Strategy

You can target both .NET Framework and modern .NET during migration:

<TargetFrameworks>net472;net8.0</TargetFrameworks>

Use #if NET472 and #if NET8_0 in source code to isolate platform-specific code.

Exercise: Take a small .NET Framework console app (targeting 4.7.2) that uses System.Drawing to resize images and AppDomain for plugin loading. Port it to .NET 8, replacing System.Drawing with SkiaSharp and AppDomain with AssemblyLoadContext. Run the portability analyzer before and after.