What Matters in ASP.NET Core 11

ASP.NET Core 11 has no single feature that fundamentally changes how web applications are built. That is not a criticism. Mature frameworks improve by removing custom infrastructure, tightening defaults and making common behavior cheaper or easier to observe.

The changes available through Preview 7 can be ranked by what they can break or simplify in a real application:

AreaOperational relevanceFirst check
Async validationRemoves sync-over-async workaroundsDependency cost and cancellation
OpenAPI 3.2Changes the generated contractEvery downstream generator and gateway
Native HTTP telemetryChanges span attributesDuplicate spans, tags and dashboard queries
Request hardeningRejects more invalid traffic correctlyProxy and protocol regression tests
SignalR auth refreshKeeps long-lived identity currentPermission loss after refresh
Blazor SSR and circuit lifecycleAvoids rendering and retained server stateCache isolation and memory under hidden tabs
C# unionsImproves contract modelingPreview and ecosystem compatibility

Release status: This assessment reflects .NET 11 Preview 7 from August 2026. APIs and defaults can still change before the supported release. Preview builds are useful for finding migration problems, not as a production target.

Async validation solves a real pipeline gap

Data Annotations are synchronous, but many validation rules need I/O. Blocking on a database or service call inside a synchronous attribute wastes threads and ignores cancellation. Repeating the same check in every endpoint scatters one policy across handlers.

.NET 11 introduces AsyncValidationAttribute and IAsyncValidatableObject. ASP.NET Core integrates them through Microsoft.Extensions.Validation for Minimal APIs and Blazor.

 1using System.ComponentModel.DataAnnotations;
 2using Microsoft.Extensions.DependencyInjection;
 3
 4public interface ICustomerDirectory
 5{
 6    Task<bool> EmailExistsAsync(
 7        string email,
 8        CancellationToken cancellationToken);
 9}
10
11public sealed class UniqueEmailAttribute : AsyncValidationAttribute
12{
13    protected override ValidationResult? IsValid(
14        object? value,
15        ValidationContext validationContext)
16    {
17        throw new InvalidOperationException(
18            "UniqueEmailAttribute requires asynchronous validation.");
19    }
20
21    protected override async Task<ValidationResult?> IsValidAsync(
22        object? value,
23        ValidationContext validationContext,
24        CancellationToken cancellationToken)
25    {
26        if (value is not string email)
27        {
28            return ValidationResult.Success;
29        }
30
31        ICustomerDirectory customerDirectory =
32            validationContext.GetRequiredService<ICustomerDirectory>();
33
34        bool exists = await customerDirectory.EmailExistsAsync(
35            email,
36            cancellationToken);
37
38        return exists
39            ? new ValidationResult("The email address is already registered.")
40            : ValidationResult.Success;
41    }
42}
43
44public sealed record CreateCustomerRequest(
45    [property: Required]
46    [property: EmailAddress]
47    [property: UniqueEmail]
48    string Email);

Registration stays small:

1WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
2
3builder.Services.AddValidation();
4builder.Services.AddScoped<ICustomerDirectory, CustomerDirectory>();

Validation still needs a strict budget. A request model with several remote validators can create fan-out before the endpoint starts. Every dependency needs cancellation and a short timeout and collection validation must not execute one query per item.

An async uniqueness check also remains advisory. Another request can insert the same value between validation and persistence. The database constraint is authoritative; validation only improves the error path.

OpenAPI 3.2 is a compatibility change

ASP.NET Core now generates OpenAPI 3.2 by default. The new vocabulary is useful, especially for streams, but the document is consumed by SDK generators, gateways, documentation portals, scanners and contract tests. Those tools will not all adopt 3.2 together.

The default-version change should be treated like any other public contract migration. If one required tool is not ready, pinning 3.1 temporarily is a valid compatibility decision:

 1using Microsoft.OpenApi;
 2
 3WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
 4
 5builder.Services.AddOpenApi(options =>
 6{
 7    options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1;
 8});
 9
10WebApplication app = builder.Build();
11
12app.MapOpenApi();
13app.Run();

The best 3.2 improvement is a more accurate Server-Sent Events contract. An SSE response can describe the schema of each event instead of appearing as one opaque string:

 1using System.Net.ServerSentEvents;
 2using System.Runtime.CompilerServices;
 3
 4app.MapGet(
 5    "/orders/stream",
 6    (CancellationToken cancellationToken) =>
 7        TypedResults.ServerSentEvents(StreamOrdersAsync(cancellationToken)));
 8
 9static async IAsyncEnumerable<SseItem<OrderStatus>> StreamOrdersAsync(
10    [EnumeratorCancellation] CancellationToken cancellationToken)
11{
12    OrderStatus[] updates =
13    [
14        new OrderStatus("order-42", "accepted"),
15        new OrderStatus("order-42", "processing"),
16        new OrderStatus("order-42", "completed")
17    ];
18
19    foreach (OrderStatus update in updates)
20    {
21        yield return new SseItem<OrderStatus>(update)
22        {
23            EventId = $"{update.OrderId}:{update.State}"
24        };
25
26        await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
27    }
28}
29
30public sealed record OrderStatus(
31    string OrderId,
32    string State);

TypedResults.ServerSentEvents matters here. Returning the enumerable directly follows normal JSON serialization and does not select the SSE result path.

Native telemetry changes the baseline

ASP.NET Core 11 adds OpenTelemetry HTTP semantic-convention attributes to the framework’s server activity. Fields such as http.request.method, url.path, http.response.status_code and server.address can now originate from the framework itself.

1using OpenTelemetry.Trace;
2
3builder.Services
4    .AddOpenTelemetry()
5    .WithTracing(tracing =>
6    {
7        tracing.AddSource("Microsoft.AspNetCore");
8        tracing.AddOtlpExporter();
9    });

OpenTelemetry.Instrumentation.AspNetCore should not be removed immediately after retargeting. The package may still provide behavior beyond the new built-in attributes or be configured through a distribution package.

The migration check should compare traces from the same requests before and after the upgrade:

  • duplicate spans or attributes;
  • renamed span fields;
  • changed status and route values;
  • new high-cardinality data;
  • broken dashboard and alert queries; and
  • changed sampling or export cost.

A semantically better tag is still an operational breaking change when production queries depend on the old name.

Security work mostly arrives through better defaults

Preview 7 narrows automatic unsafe cross-origin request protection to endpoints carrying antiforgery metadata. Form-binding endpoints participate; a normal JSON MapPost does not suddenly require an antiforgery token.

Migration tests should cover that distinction explicitly: same-origin form posts, rejected cross-origin form posts, legitimate non-browser clients and plain JSON APIs.

Authorization metadata also becomes consistent across MVC, SignalR, AuthorizeView and AuthorizeRouteView. Applications with custom IAuthorizationRequirementData attributes should run the same requirement tests across those surfaces rather than assuming identical composition.

Kestrel and middleware now reject more malformed content lengths, invalid connection-specific headers, fragmented trailers, multipart headers, chunked requests and rewrite targets correctly. Malformed HTTP/1.1 parsing also uses a cheaper non-throwing path.

Most applications need no new code for these fixes. They need representative proxy and protocol tests. A reverse proxy depending on invalid behavior is still a migration problem even when Kestrel is correct to reject it.

SignalR authentication can outlive one token

A SignalR connection may remain open longer than the token used during negotiation. ASP.NET Core 11 can refresh authentication without dropping the hub connection:

 1using System.Security.Claims;
 2using Microsoft.AspNetCore.SignalR;
 3
 4app.MapHub<OperationsHub>("/operations", options =>
 5{
 6    options.CloseOnAuthenticationExpiration = true;
 7    options.EnableAuthenticationRefresh = true;
 8    options.OnAuthenticationRefresh = context =>
 9        ValueTask.FromResult(true);
10});
11
12public sealed class OperationsHub : Hub
13{
14    public override Task OnAuthenticationRefreshedAsync()
15    {
16        ClaimsPrincipal? refreshedUser = Context.User;
17        return Task.CompletedTask;
18    }
19}

The client must also request refreshes, either explicitly or through its authentication-refresh configuration and supply fresh credentials. Enabling the server option alone does not renew tokens. The SignalR authentication guide documents both sides of the protocol.

Refreshing identity is only half the feature. If the new principal lost permission, existing group membership and subscriptions may now be wrong. The application must remove access, reject future calls or close the connection. That transition requires an explicit test.

Regular hub invocations can also propagate client cancellation to a server method:

1public sealed class OperationsHub : Hub
2{
3    public async Task RebuildProjectionAsync(
4        CancellationToken cancellationToken)
5    {
6        await ProjectionRebuilder.RebuildAsync(cancellationToken);
7    }
8}

Cancellation remains cooperative. Downstream work must observe the token and a canceled invocation must not leave a transaction half committed.

Zstandard is useful after measurement

Zstandard joins the existing response-compression and request-decompression middleware:

1WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
2
3builder.Services.AddResponseCompression();
4builder.Services.AddRequestDecompression();
5
6WebApplication app = builder.Build();
7
8app.UseResponseCompression();
9app.UseRequestDecompression();

The algorithm often gives service-to-service traffic a good ratio for its CPU cost. Payload size, content type, quality level, proxy behavior and actual client support should still be measured before broad adoption.

Request decompression deserves the stricter review. A small compressed body can expand into substantial memory and CPU work. The framework caps the Zstandard window, but application request-size limits, authentication and timeouts remain necessary.

Response compression now consistently emits Vary: Accept-Encoding, including uncompressed responses. That prevents shared caches from confusing representations.

Blazor 11 is mainly about doing less

The Blazor release contains many features. The useful direction is simpler: keep more pages statically rendered, avoid rebuilding expensive fragments and release inactive circuit resources.

Static SSR forms gain client-side validation while the server remains authoritative. QuickGrid can sort and paginate through URL-driven enhanced forms without requiring an interactive circuit. Avoiding an unnecessary render mode reduces client payload, server state, reconnect behavior and operational complexity.

CacheView skips component execution

CacheView caches rendered HTML for an SSR component subtree. On a hit, child components are not constructed or rendered:

1<CacheView ExpiresAfter="TimeSpan.FromMinutes(5)"
2           VaryByRoute="productId"
3           VaryByQuery="page,pageSize"
4           VaryByCulture="true">
5    <ProductSummary ProductId="productId" />
6</CacheView>

That is more valuable than only caching response transfer. It is also a data-isolation boundary. Tenant, user, culture, feature flags, pricing context and experiments may all affect the HTML. Every missing variation dimension risks serving the wrong content.

ASP.NET Core can require VaryByUser for components such as AuthorizeView, but application-specific context still needs explicit keys and tests.

Server circuits can pause

Interactive Server can pause inactive circuits, allowing hidden tabs to release server resources. The following configuration requires the Microsoft.AspNetCore.Components.Server.AutoPause package at a version matching the ASP.NET Core preview:

 1app.MapRazorComponents<App>()
 2    .AddInteractiveServerRenderMode()
 3    .WithBrowserOptions(options =>
 4    {
 5        options.AddAutoPause(pauseOptions =>
 6        {
 7            pauseOptions.Enabled = true;
 8            pauseOptions.HiddenDelay = TimeSpan.FromMinutes(2);
 9        });
10    });

The browser avoids automatic pauses while inputs are modified, media or transfers are active or circuit work is still running. Relevant measurements include memory, pause success, restore latency, expired state and behavior during deployments. Request throughput alone says little about a server holding thousands of inactive circuits.

The new ASP.NET Core-based Blazor WebAssembly Gateway also replaces the old development server. It provides SPA fallback and YARP proxying for same-origin local development. It reduces CORS friction but does not define the production topology; authentication, TLS, forwarded headers and proxy limits remain application decisions.

C# unions are promising, not yet a contract foundation

Preview 7 can represent C# unions across ASP.NET Core JSON, Minimal APIs, MVC, SignalR, Blazor state and OpenAPI. This sample requires the matching .NET 11 preview SDK and <LangVersion>preview</LangVersion>:

 1app.MapPost(
 2    "/payments",
 3    (PaymentMethod paymentMethod) =>
 4        TypedResults.Accepted());
 5
 6public sealed record CardPayment(
 7    string LastFourDigits);
 8
 9public sealed record BankTransfer(
10    string Iban);
11
12public union PaymentMethod(
13    CardPayment,
14    BankTransfer);

This can replace hand-written discriminator hierarchies. It should still remain outside a long-lived public API today: the language feature is preview, binding is JSON-only, SignalR requires its JSON protocol and third-party generators may not understand the resulting anyOf schema.

That makes unions an excellent prototype and compatibility-test target, not a stable wire-format decision yet.

Smaller changes for the upgrade branch

  • Replace obsolete EditContext.Validate calls with ValidateAsync.
  • Rename WebApplicationFactory.ConfigureHostApplicationBuilder overrides to ConfigureWebApplicationBuilder.
  • Remove dependencies on deleted MVC compatibility APIs.
  • Replace the deprecated Blazor WebAssembly DevServer.
  • Remove Microsoft.AspNetCore.Grpc.Swagger, which no longer exists.
  • Test encoded / behavior in unusual request targets.

These are not architectural features, but several can stop compilation or integration tests immediately.

Evaluation sequence

  1. Retarget one representative service in an isolated branch.
  2. Resolve compiler and analyzer changes without broad suppressions.
  3. Run every OpenAPI consumer against the generated 3.2 document.
  4. Compare request traces, dashboards and telemetry cost.
  5. Exercise form endpoints from same-origin, cross-origin and non-browser clients.
  6. Load-test async validators with slow dependencies and large invalid payloads.
  7. Test SignalR token refresh, permission loss, redirects and cancellation.
  8. Measure Blazor cache isolation and circuit memory under realistic tab activity.
  9. Review the final breaking-change documentation before production rollout.

What actually matters

The strongest ASP.NET Core 11 changes make existing boundaries more honest. Async validation acknowledges I/O without hiding a blocking call. OpenAPI describes modern contracts more accurately. Native telemetry reduces framework gaps. SignalR identity can remain current. Blazor can avoid work instead of making every interaction expensive.

The release should not be measured by its number of new APIs. Its value lies in how much custom infrastructure can be deleted, which contracts become more accurate and whether applications behave better under real traffic. On that basis, ASP.NET Core 11 is useful, but it belongs in an integration branch long before a production deployment.

For a focused treatment of the framework’s API error contract, see Problem Details in ASP.NET Core and .NET 11.

The detailed source for this snapshot is the .NET 11 Preview 7 announcement and the ASP.NET Core Preview 7 component release notes . Earlier changes are collected in the .NET 11 release notes .


Let's Work Together

Looking for an experienced Platform Architect or Engineer for your next project? Whether it's cloud migration, platform modernization or building new solutions from scratch - I'm here to help you succeed.

New Platforms

Modernization

Training & Consulting