The winds of change are blowing in the direction of .NET 10, and many teams are adjusting their sails to navigate towards new and bold adventures. Exciting times are ahead. As .NET 10 marks the long-term support (LTS) version of the SDK and runtime, now is a great time to plan and strategize. After all, we all have limited resources, developer cycles, and energy when upgrading. You don’t want your ship to hit any unexpected choppy waters.
In this post, Duende has scoured the currently documented .NET 10 breaking changes and found some items you want to be mindful of when upgrading. Hopefully, many of these items will be uneventful in your upgrade, but some may leave you stranded on a deserted island called frustration. In no particular order, let’s see what they are and why you may want to mark them on your upgrade map.
Cookie Login Redirects Are Turned Off For Known API Endpoints
The ASP.NET Core pipeline is configurable to meet a wide variety of needs. Many of our Duende customers mix OAuth-secured API endpoints alongside ASP.NET Core MVC or Razor Pages UIs. It's only natural that many .NET developers would notice a typical behavior: their API endpoints accidentally trigger a challenge response, attempting to redirect the caller to the Duende IdentityServer instance. The redirect behavior is not what most developers intend to happen. A caller would likely want to see a 401 Unauthorized or 403 Forbidden response - it's an API after all!
In .NET 10, any endpoint secured by cookie authentication and marked with an IApiEndpointMetadata interface will no longer redirect to a login or access-denied URI. The change includes ApiController endpoints, Minimal API endpoints that handle incoming JSON requests or outgoing JSON responses, endpoints using TypedResults, or SignalR endpoints.
While most Duende customers will welcome this change, it is still a behavioral deviation from the past. As in, the change could impact already existing deployments. Be mindful of this change and test accordingly when upgrading.
IActionContextAccessor And ActionContextAccessor Are Obsolete
.NET now marks IActionContextAccessor and ActionContextAccessor abstractions as obsolete. While not used directly in Duende IdentityServer, some customers may use these abstractions in customizations to their deployments.
Since ASP.NET Core has transitioned to Endpoint Routing, you can substitute any use of IActionContextAccessor with HttpContextAccessor or IHttpContextAccessor.
public class MyService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public MyService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void DoSomething()
{
var httpContext = _httpContextAccessor.HttpContext;
var endpoint = httpContext?.GetEndpoint();
var actionDescriptor = endpoint?.Metadata.GetMetadata<ActionDescriptor>();
// Use action descriptor metadata.
}
}
Note that HttpContext is still only available within the lifetime of an active web request.
IPNetwork And ForwardedHeadersOptions.KnownNetworks Are Obsolete
Many Duende customers, especially those using our Enterprise edition, rely heavily on Forwarded Headers to deploy load-balanced security solutions. This requires configuring ASP.NET Core applications appropriately. Configuration involves setting the ForwardedHeadersMiddlware and its options.
In .NET 10, when using KnownNetworks in the ForwardHeaderOptions, you’ll start receiving an obsolete warning, guiding you to use KnownIpNetworks instead.
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
KnownIpNetworks.Add(new(IPAddress.Loopback, 8))
});
With Duende IdentityServer, you can use the discovery document to verify that forward headers are set and processed correctly in staging environments.
Razor Run-Time Compilation Is Obsolete
A developer would use the Razor run-time compilation feature to create a faster feedback loop. Previously, this feature would recompile changed .cshtml files during runtime. The technique avoids a typically slow restart phase. .NET now marks the AddRazorRuntimeCompilation method as obsolete in favor of tooling-based Hot Reload, which developers can find in Visual Studio, C# Dev Kit for VS Code, and JetBrains Rider.
If you continue to use the feature, you’ll see the following warning message.
warning ASPDEPR003: Razor run-time compilation is obsolete and is not recommended for production scenarios.
For production scenarios, use the default build time compilation. For development scenarios, use Hot Reload instead.
For more information, visit https://aka.ms/aspnet/deprecate/003.
Developers who treat warnings as errors may see their builds fail until they’ve addressed this particular issue. While we do not use Razor runtime compilation in our templates, we can imagine developers may have added it to improve their workflows.
WebHostBuilder, IWebHost, And WebHost Are Obsolete
This one hurts us the most, since Duende’s source code uses WebHostBuilder across our codebase and test suite. Have no fear. We are currently modernizing and will be ready for .NET 10. That said, if you have an existing Duende IdentityServer deployment based on past templates, you’ll need to adjust the code slightly to avoid these warnings.
warning ASPDEPR004: WebHostBuilder is deprecated in favor of HostBuilder and WebApplicationBuilder.
For more information, visit https://aka.ms/aspnet/deprecate/004.
As the message notes, you’ll need to move from WebHostBuilder over to HostBuilder or WebApplicationBuilder. If you’re injecting IWebHost as a dependency, consider switching to IHost or creating a targeted abstraction to pass the required information.
Default .NET Container Images Now Use Ubuntu
For previous versions, the .NET team based container images on Debian. Starting with .NET 10, the .NET team has moved to Ubuntu as the base image. The reason for the change was that Ubuntu has longer support cycles, meaning the .NET version within the container will be unsupported before the Linux distribution hosting your application. There are unlikely to be any noticeable differences, but it’s better to be safe than sorry.
Uri Length Limits Removed When Creating New Instances
The change to Uri length limits could generally be a good thing for developers, but it may also cause more runtime issues. Starting in .NET 10, there are no longer runtime exceptions thrown when you create a Uri with more than 65,000 characters.
new Uri($"https://host/{new string('a', 100_000)}")
While you can now create large Uri instances, the target destination’s server must be capable of accepting these large payloads. If they are not, well, expect exceptions. Exercise common sense and judgement, please.
X509Certificate And PublicKey Key Parameters Can Be Null
A minor change to the X509Certificate class behavior could cause runtime exceptions you should watch out for.
The X
509Certificate,X509Certificate2, andPublicKeyclasses expose information about the Subject Public Key Info. One of the properties of the Subject Public Key Info is the parameters for the algorithm. A Subject Public Key Info is not required to contain algorithm parameters. Previously, this was represented as an empty byte array, which is not valid ASN.1. Attempting to encode or decode it would result in an exception. To more clearly represent absent key parameters,nullis now returned, and the members that return algorithm parameters have been annotated to return nullable values.
When working with a certificate, remember to code defensively and check whether the result is not null.
byte[] parameters = certificate.GetKeyAlgorithmParameters();
if (parameters == null)
{
// Handle the absence of algorithm parameters
}
When working with Duende IdentityServer, we have a few customers who deal with X509Certificate instances in code paired with Duende IdentityModel. Now is a good time to go back and verify proper nullability checks are enabled and followed.
Conclusion
.NET 10 is a great time to upgrade your application and its dependencies, as the change can bring with it improved application performance and enhanced features. While it's exciting, you should proceed with caution. With a bit of information, you can now upgrade your identity solutions with confidence.
Let us know in the comments if you’re planning to upgrade to .NET 10, or maybe you already have and would like to share your experience with others. If you’re in the process of upgrading, join our Duende community discussions and let us help by answering questions.