Navigating Breaking Changes in .NET 10

.NET Development

A comprehensive guide to breaking changes introduced in .NET 10, categorized by technology area to assist developers migrating applications. Includes definitions of binary, source, and behavioral incompatibilities.

This document outlines significant breaking changes introduced in .NET 10, crucial for developers migrating existing applications. Understanding these changes, categorized by technology area such as ASP.NET Core, Windows Forms, or Core .NET libraries, is essential for a smooth transition.

Each breaking change is classified into one of the following types:

  • Binary incompatible: Existing binaries might fail to load or execute when run against the new runtime or component, necessitating recompilation.
  • Source incompatible: Existing source code may require modifications to compile successfully when recompiled using the new SDK or component, or when targeting the new runtime.
  • Behavioral change: Existing code and binaries might exhibit different behavior at runtime. If the new behavior is undesirable, updates and recompilation of the existing code would be required.

Important Note: This article is a work in progress and does not yet constitute a comprehensive list of all breaking changes in .NET 10.

ASP.NET Core

  • Cookie login redirects disabled for known API endpoints: Behavioral change
  • Deprecation of WithOpenApi extension method: Source incompatible
  • Exception diagnostics suppressed when TryHandleAsync returns true: Behavioral change
  • IActionContextAccessor and ActionContextAccessor are obsolete: Source incompatible/behavioral change
  • IncludeOpenAPIAnalyzers property and MVC API analyzers are deprecated: Source incompatible
  • IPNetwork and ForwardedHeadersOptions.KnownNetworks are obsolete: Source incompatible
  • Microsoft.Extensions.ApiDescription.Client package deprecated: Source incompatible
  • Razor runtime compilation is obsolete: Source incompatible
  • WebHostBuilder, IWebHost, and WebHost are obsolete: Source incompatible

Containers

  • Default .NET images use Ubuntu: Behavioral change

Core .NET libraries

  • ActivitySource.CreateActivity and ActivitySource.StartActivity behavior change: Behavioral change
  • Arm64 SVE nonfaulting loads require mask: Binary/source incompatible
  • BufferedStream.WriteByte no longer performs implicit flush: Behavioral change
  • C# 14 overload resolution with span parameters: Behavioral change
  • Consistent shift behavior in generic math: Behavioral change
  • Default trace context propagator updated to W3C standard: Behavioral change
  • DriveInfo.DriveFormat returns Linux filesystem types: Behavioral change
  • DynamicallyAccessedMembers annotation removed from DefaultValueAttribute ctor: Binary/source incompatible
  • Explicit struct Size disallowed with InlineArray: Binary incompatible
  • FilePatternMatch.Stem changed to non-nullable: Source incompatible/behavioral change
  • GnuTarEntry and PaxTarEntry no longer includes atime and ctime by default: Behavioral change
  • LDAP DirectoryControl parsing is now more stringent: Behavioral change
  • MacCatalyst version normalization: Behavioral change
  • .NET runtime no longer provides default termination signal handlers: Behavioral change
  • System.Linq.AsyncEnumerable included in core libraries: Source incompatible
  • Type.MakeGenericSignatureType argument validation: Behavioral change

Cryptography

  • Composite MLDsa updated to draft-08: Behavioral change
  • CoseSigner.Key can be null: Behavioral/source incompatible change
  • MLDsa and SlhDsa 'SecretKey' members renamed: Source incompatible
  • OpenSSL cryptographic primitives aren't supported on macOS: Behavioral change
  • OpenSSL 1.1.1 or later required on Unix: Behavioral change
  • X500DistinguishedName validation is stricter: Behavioral change
  • X509Certificate and PublicKey key parameters can be null: Behavioral/source incompatible change
  • Environment variable renamed to DOTNET_OPENSSL_VERSION_OVERRIDE: Behavioral change

Entity Framework Core

  • Breaking changes in EF Core 10 (Note: Details are not provided in the source for EF Core beyond this title.)

Extensions

  • BackgroundService runs all of ExecuteAsync as a Task: Behavioral change
  • Fix issues in GetKeyedService() and GetKeyedServices() with AnyKey: Behavioral change
  • Null values preserved in configuration: Behavioral change
  • Message no longer duplicated in Console log output: Behavioral change
  • ProviderAliasAttribute moved to Microsoft.Extensions.Logging.Abstractions assembly: Source incompatible
  • Removed DynamicallyAccessedMembers annotation from trim-unsafe Microsoft.Extensions.Configuration code: Binary incompatible

Globalization

  • Environment variable renamed to DOTNET_ICU_VERSION_OVERRIDE: Behavioral change

Install tool

  • dotnet.acquire API for VS Code no longer always downloads latest: Behavioral change

Interop

  • Casting IDispatchEx COM object to IReflect fails: Behavioral change
  • Single-file apps no longer look for native libraries in executable directory: Behavioral change
  • Specifying DllImportSearchPath.AssemblyDirectory only searches the assembly directory: Behavioral change

Networking

  • HTTP/3 support disabled by default with PublishTrimmed: Source incompatible
  • Streaming HTTP responses enabled by default in browser HTTP clients: Behavioral change
  • Uri length limits removed: Behavioral change

Reflection

  • More restricted annotations on InvokeMember/FindMembers/DeclaredMembers: Behavioral/source incompatible

SDK and MSBuild

  • .NET CLI --interactive defaults to true in user scenarios: Behavioral change
  • dotnet CLI commands log non-command-relevant data to stderr: Behavioral change
  • .NET tool packaging creates RuntimeIdentifier-specific tool packages: Behavioral change
  • Default workload configuration from 'loose manifests' to 'workload sets' mode: Behavioral change
  • Code coverage EnableDynamicNativeInstrumentation defaults to false: Behavioral change
  • dnx.ps1 file is no longer included in .NET SDK: Source incompatible
  • dotnet new sln defaults to SLNX file format: Behavioral change
  • dotnet package list performs restore: Behavioral change
  • dotnet restore audits transitive packages: Behavioral change
  • dotnet tool install --local creates manifest by default: Behavioral change
  • dotnet watch logs to stderr instead of stdout: Behavioral change
  • project.json not supported in dotnet restore: Source incompatible
  • SHA-1 fingerprint support deprecated in dotnet nuget sign: Behavioral change
  • MSBUILDCUSTOMBUILDEVENTWARNING escape hatch removed: Behavioral change
  • MSBuild custom culture resource handling: Behavioral change
  • NU1510 is raised for direct references pruned by NuGet: Source incompatible
  • NuGet packages with no runtime assets aren't included in deps.json: Source incompatible
  • PackageReference without a version raises an error: Behavioral change
  • PrunePackageReference privatizes direct prunable references: Behavioral change
  • HTTP warnings promoted to errors in dotnet package list and dotnet package search: Behavioral/source incompatible change
  • NUGET_ENABLE_ENHANCED_HTTP_RETRY environment variable removed: Behavioral change
  • NuGet logs an error for invalid package IDs: Behavioral change
  • ToolCommandName not set for non-tool packages: Source incompatible

Serialization

  • System.Text.Json checks for property name conflicts: Behavioral change
  • XmlSerializer no longer ignores properties marked with ObsoleteAttribute: Behavioral change

Windows Forms

  • API obsoletions: Source incompatible
  • Applications referencing both WPF and WinForms must disambiguate MenuItem and ContextMenu types: Source incompatible
  • Renamed parameter in HtmlElement.InsertAdjacentElement: Source incompatible
  • TreeView checkbox image truncation: Behavioral change
  • StatusStrip uses System RenderMode by default: Behavioral change
  • System.Drawing OutOfMemoryException changed to ExternalException: Behavioral change

Windows Presentation Foundation (WPF)

  • Empty ColumnDefinitions and RowDefinitions are disallowed: Source incompatible
  • Incorrect usage of DynamicResource causes application crash: Source incompatible/behavioral change