From a6a21553065ef00280f45e9365abf97aa365bac2 Mon Sep 17 00:00:00 2001 From: danroth27 Date: Wed, 29 Apr 2026 16:50:18 -0700 Subject: [PATCH 1/6] [release-notes] ASP.NET Core in .NET 11 Preview 4 (initial) --- release-notes/11.0/preview/preview4/aspnetcore.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 release-notes/11.0/preview/preview4/aspnetcore.md diff --git a/release-notes/11.0/preview/preview4/aspnetcore.md b/release-notes/11.0/preview/preview4/aspnetcore.md new file mode 100644 index 0000000000..31e7d7ed61 --- /dev/null +++ b/release-notes/11.0/preview/preview4/aspnetcore.md @@ -0,0 +1,3 @@ +# ASP.NET Core in .NET 11 Preview 4 - Release Notes + +_Authored content pending — agent assigned._ From 975a3cd9e8f2dcb617bd845a8ff5797aea124126 Mon Sep 17 00:00:00 2001 From: danroth27 Date: Wed, 29 Apr 2026 17:11:33 -0700 Subject: [PATCH 2/6] [release-notes] Author aspnetcore.md content --- .../11.0/preview/preview4/aspnetcore.md | 184 +++++++++++++++++- 1 file changed, 183 insertions(+), 1 deletion(-) diff --git a/release-notes/11.0/preview/preview4/aspnetcore.md b/release-notes/11.0/preview/preview4/aspnetcore.md index 31e7d7ed61..c7301b4f19 100644 --- a/release-notes/11.0/preview/preview4/aspnetcore.md +++ b/release-notes/11.0/preview/preview4/aspnetcore.md @@ -1,3 +1,185 @@ # ASP.NET Core in .NET 11 Preview 4 - Release Notes -_Authored content pending — agent assigned._ +.NET 11 Preview 4 includes new ASP.NET Core features and improvements: + +- [Support for the HTTP QUERY method](#support-for-the-http-query-method) +- [SupplyParameterFromTempData for Blazor](#supplyparameterfromtempdata-for-blazor) +- [Server-initiated Blazor Server circuit pause](#server-initiated-blazor-server-circuit-pause) +- [Virtualize keeps the viewport stable when content above it changes](#virtualize-keeps-the-viewport-stable-when-content-above-it-changes) +- [Blazor WebAssembly service defaults template](#blazor-webassembly-service-defaults-template) +- [MCP Server template ships with the .NET SDK](#mcp-server-template-ships-with-the-net-sdk) +- [TLS handshake observability in Kestrel](#tls-handshake-observability-in-kestrel) +- [Response compression always emits `Vary: Accept-Encoding`](#response-compression-always-emits-vary-accept-encoding) +- [OpenAPI and minimal API improvements](#openapi-and-minimal-api-improvements) +- [Smaller Blazor WebAssembly publish output](#smaller-blazor-webassembly-publish-output) +- [Breaking changes](#breaking-changes) +- [Bug fixes](#bug-fixes) +- [Community contributors](#community-contributors) + +ASP.NET Core updates in .NET 11: + +- [What's new in ASP.NET Core in .NET 11](https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-11) + +## Support for the HTTP QUERY method + +ASP.NET Core now recognizes [HTTP QUERY](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/) as a first-class HTTP method in routing, minimal APIs, and OpenAPI document generation ([dotnet/aspnetcore #65714](https://github.com/dotnet/aspnetcore/pull/65714)). QUERY is a proposed safe, idempotent method that lets clients send a request body when describing a search — useful when a query is too large or too structured to fit in a URL. + +```csharp +var app = WebApplication.Create(); + +app.MapMethods("/search", ["QUERY"], (SearchRequest request) => + SearchService.Run(request)); + +app.Run(); +``` + +The method shows up in generated OpenAPI documents alongside `GET`, `POST`, and friends, so client generators and API explorers pick it up automatically. + +Thank you [@kilifu](https://github.com/kilifu) for this contribution! + +## `SupplyParameterFromTempData` for Blazor + +A new `[SupplyParameterFromTempData]` attribute reads and writes TempData values directly on a Blazor SSR component property, in the same style as `[SupplyParameterFromQuery]` and `[SupplyParameterFromForm]` ([dotnet/aspnetcore #65306](https://github.com/dotnet/aspnetcore/pull/65306)). + +```razor +@page "/account/manage" + + + +@code { + [SupplyParameterFromTempData] + public string? StatusMessage { get; set; } +} +``` + +If the property name doesn't match the TempData key you want, set `Name` on the attribute. Setting the property writes through to TempData so the next request can read it — handy for status messages that survive a redirect-after-post. + +The Blazor Identity project template was rewritten to use this attribute instead of the previous custom status-message cookie ([dotnet/aspnetcore #65752](https://github.com/dotnet/aspnetcore/pull/65752)). + +## Server-initiated Blazor Server circuit pause + +`Circuit.RequestCircuitPauseAsync` lets server-side code ask the connected Blazor client to begin the graceful circuit-pause flow ([dotnet/aspnetcore #66455](https://github.com/dotnet/aspnetcore/pull/66455)). Until now, pause was only triggered by client-side navigation; this gives operators a programmatic way to drain circuits during deployments or load-balancer rebalancing. + +```csharp +public class RebalanceService(CircuitRegistry circuits) +{ + public async Task DrainAsync(CancellationToken ct) + { + foreach (var circuit in circuits.GetActiveCircuits()) + { + await circuit.RequestCircuitPauseAsync(); + } + } +} +``` + +The method returns `true` when the client was successfully asked to begin pausing. Clients can defer the request via the optional `onPauseRequested` callback in `CircuitStartOptions`. + + + +## Virtualize keeps the viewport stable when content above it changes + +Preview 3 taught Blazor's `Virtualize` to handle items with different heights. Preview 4 builds on that with viewport stability: visible items stay in place when items above the viewport change height, and when items are prepended to the collection ([dotnet/aspnetcore #65951](https://github.com/dotnet/aspnetcore/pull/65951)). + +The component uses native CSS scroll anchoring where the browser supports it and falls back to manual scroll compensation otherwise (notably for `` layouts and Safari). Apps using `Virtualize` get this automatically — no API changes required. + +## Blazor WebAssembly service defaults template + +A new `blazor-wasm-servicedefaults` template scaffolds a service-defaults library for Blazor WebAssembly clients with .NET Aspire integration ([dotnet/aspnetcore #64807](https://github.com/dotnet/aspnetcore/pull/64807)). It mirrors the service-defaults pattern that Aspire already uses for server projects and `dotnet/maui` ships for MAUI clients. + +```bash +dotnet new blazor-wasm-servicedefaults -o MyBlazorApp.ServiceDefaults +``` + +The generated library wires up OpenTelemetry logging/metrics/tracing with the OTLP exporter, service discovery via `Microsoft.Extensions.ServiceDiscovery`, and standard HTTP resilience handlers from `Microsoft.Extensions.Http.Resilience`. Reference the project from your Blazor WebAssembly client and call the generated extension method during startup: + +```csharp +builder.AddBlazorClientServiceDefaults(); +``` + +## MCP Server template ships with the .NET SDK + +The `mcpserver` project template, previously available only by installing `Microsoft.McpServer.ProjectTemplates`, now ships as a bundled template in the .NET SDK ([dotnet/aspnetcore #66520](https://github.com/dotnet/aspnetcore/pull/66520)). + +```bash +dotnet new mcpserver -o MyMcpServer +``` + +Moving the template into ASP.NET Core makes it discoverable from `dotnet new list` without a separate install step, and aligns its servicing with the rest of the web stack. + +## TLS handshake observability in Kestrel + +Two related changes make it easier to diagnose and customize TLS connections in Kestrel. + +`ITlsHandshakeFeature` now exposes the exception thrown during a failed TLS handshake, so middleware and logging can record why a connection failed instead of seeing a bare `IOException` further up the stack ([dotnet/aspnetcore #65807](https://github.com/dotnet/aspnetcore/pull/65807)). The feature continues to work after the handshake fails — Kestrel snapshots the relevant fields off the underlying `SslStream` before it is disposed. + +The `TlsClientHelloBytesCallback` option on `HttpsConnectionAdapterOptions` was reworked as a connection middleware ([dotnet/aspnetcore #65808](https://github.com/dotnet/aspnetcore/pull/65808)). The previous callback shape is now obsolete; configure ClientHello inspection via the connection-builder pipeline instead. + + + +## Response compression always emits `Vary: Accept-Encoding` + +The response-compression middleware now adds `Vary: Accept-Encoding` to every response when compression is enabled, even when the response itself isn't compressed ([dotnet/aspnetcore #55092](https://github.com/dotnet/aspnetcore/pull/55092)). This prevents shared caches and CDNs from serving a compressed payload to a client that didn't ask for one (or vice versa). + +Thank you [@pedrobsaila](https://github.com/pedrobsaila) for this contribution! + +## OpenAPI and minimal API improvements + +Two changes round out the minimal API + OpenAPI experience this preview: + +- **File result types appear in OpenAPI documents.** `FileStreamResult`, `FileContentHttpResult`, and `FileStreamHttpResult` are now described as binary string schemas in generated OpenAPI documents, so clients see accurate response shapes for endpoints that stream files ([dotnet/aspnetcore #64562](https://github.com/dotnet/aspnetcore/pull/64562)). Thank you [@marcominerva](https://github.com/marcominerva) for this contribution! +- **Endpoint filters can observe parameter-binding failures.** When a minimal API endpoint has filters configured and its delegate returns `ValueTask`, the filter pipeline now runs even if parameter binding fails. Filters can read the 400 response and substitute their own. Endpoints without filters continue to short-circuit with a 400 as before ([dotnet/aspnetcore #64539](https://github.com/dotnet/aspnetcore/pull/64539)). Thank you [@marcominerva](https://github.com/marcominerva) for this contribution! + +## Smaller Blazor WebAssembly publish output + +Two trimming changes shrink published Blazor WebAssembly apps that don't use OpenTelemetry or hot reload: + +- The `ComponentsMetrics` and `ComponentsActivitySource` types are now gated behind a `[FeatureSwitchDefinition]`, so the trimmer can drop the metrics and tracing call paths from `Renderer` and friends when `System.Diagnostics.Metrics.Meter.IsSupported` is `false` (the default for trimmed apps) ([dotnet/aspnetcore #65901](https://github.com/dotnet/aspnetcore/pull/65901)). +- `HotReloadManager` now exposes a feature-switched `IsSupported` property tied to `System.Reflection.Metadata.MetadataUpdater.IsSupported`, so the trimmer can eliminate hot-reload caches and metadata-update handler registrations across the renderer when published ([dotnet/aspnetcore #65903](https://github.com/dotnet/aspnetcore/pull/65903)). + +Apps that use OpenTelemetry or hot reload aren't affected — the feature switches default on in those configurations. + +## Breaking changes + +- **`%2F` is preserved in HTTP/1.1 absolute-form request targets.** Previously, a request like `GET http://host/a%2Fb` was decoded to a path of `/a/b`, while `GET /a%2Fb` (origin-form) preserved the encoded slash. Both forms now resolve to `/a%2Fb`. Apps that depended on the inconsistent absolute-form behavior should update their routing or middleware to expect the encoded segment ([dotnet/aspnetcore #65930](https://github.com/dotnet/aspnetcore/pull/65930)). +- **`HttpsConnectionAdapterOptions.TlsClientHelloBytesCallback` is obsolete.** Use the new connection middleware shape introduced in [dotnet/aspnetcore #65808](https://github.com/dotnet/aspnetcore/pull/65808). The property continues to work in 11.0 but produces an obsoletion warning. + + + +## Bug fixes + +- **Blazor** + - Fixed an `InvalidOperationException` when navigating to `/Error` in newly scaffolded Blazor Server apps. The template now declares `RequestId` as `public` so `[PersistentState]` can read it ([dotnet/aspnetcore #66245](https://github.com/dotnet/aspnetcore/pull/66245)). + - Fixed a truncated gzip payload for `resource-collection.js.gz` that caused some clients to reject the response. The endpoint now writes the gzip footer before serving the bytes ([dotnet/aspnetcore #66242](https://github.com/dotnet/aspnetcore/pull/66242)). + - Fixed an "Interop methods are already registered for renderer 1" error when a Blazor Server reconnect fell back to resume after the original circuit had expired ([dotnet/aspnetcore #66275](https://github.com/dotnet/aspnetcore/pull/66275)). +- **Routing** + - Fixed `NegotiationMatcherPolicy` invalidating higher-priority endpoints when a lower-priority endpoint shared a DFA path node and carried `ContentEncodingMetadata`. Content-encoding negotiation now disambiguates only between representations of the same resource ([dotnet/aspnetcore #65973](https://github.com/dotnet/aspnetcore/pull/65973)). +- **MVC** + - Fixed `JsonSerializerSettings.DateFormatString` overwriting `DateFormatHandling` when copying serializer settings ([dotnet/aspnetcore #61251](https://github.com/dotnet/aspnetcore/pull/61251)). +- **Templates** + - Renamed the standalone `.NET Web Worker` template to `Blazor Web Worker`, added `InvokeVoidAsync` on `WebWorkerClient`, and added cancellation/timeout support to worker creation and invocation ([dotnet/aspnetcore #66070](https://github.com/dotnet/aspnetcore/pull/66070)). + - Removed the obsolete `net11.0` framework-choice descriptions from the `BlazorWebWorker` template ([dotnet/aspnetcore #66261](https://github.com/dotnet/aspnetcore/pull/66261)). + - Added `Microsoft.Data.SqlClient.Extensions.Azure` to the MVC, Blazor, and Razor Pages Individual Auth templates so Azure App Service deployments using `Authentication=Active Directory Default` work without a separate package install ([dotnet/aspnetcore #66179](https://github.com/dotnet/aspnetcore/pull/66179)). +- **Middleware** + - Clarified `UseStatusCodePages` documentation to call out that the default options handler prefers Problem Details when `IProblemDetailsService` is registered, and falls back to plain text otherwise ([dotnet/aspnetcore #66172](https://github.com/dotnet/aspnetcore/pull/66172)). + +## Community contributors + +Thank you contributors! ❤️ + +- [@Emik03](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3AEmik03) +- [@kilifu](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3Akilifu) +- [@marcominerva](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3Amarcominerva) +- [@MatthewSteeples](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3AMatthewSteeples) +- [@pedrobsaila](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3Apedrobsaila) From 33c88bdb4ad182e0b0d4413eb3ff788c14604e9e Mon Sep 17 00:00:00 2001 From: danroth27 Date: Wed, 29 Apr 2026 21:04:21 -0700 Subject: [PATCH 3/6] Add 11.0-preview4 milestone filter to community-contributor links --- release-notes/11.0/preview/preview4/aspnetcore.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/release-notes/11.0/preview/preview4/aspnetcore.md b/release-notes/11.0/preview/preview4/aspnetcore.md index c7301b4f19..4901d836ca 100644 --- a/release-notes/11.0/preview/preview4/aspnetcore.md +++ b/release-notes/11.0/preview/preview4/aspnetcore.md @@ -178,8 +178,8 @@ Apps that use OpenTelemetry or hot reload aren't affected — the feature switch Thank you contributors! ❤️ -- [@Emik03](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3AEmik03) -- [@kilifu](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3Akilifu) -- [@marcominerva](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3Amarcominerva) -- [@MatthewSteeples](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3AMatthewSteeples) -- [@pedrobsaila](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3Apedrobsaila) +- [@Emik03](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3AEmik03+milestone%3A11.0-preview4) +- [@kilifu](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3Akilifu+milestone%3A11.0-preview4) +- [@marcominerva](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3Amarcominerva+milestone%3A11.0-preview4) +- [@MatthewSteeples](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3AMatthewSteeples+milestone%3A11.0-preview4) +- [@pedrobsaila](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+author%3Apedrobsaila+milestone%3A11.0-preview4) From 8a10d27591396ae13ac9c40559a9eb64167bbc9c Mon Sep 17 00:00:00 2001 From: danroth27 Date: Thu, 30 Apr 2026 07:00:03 -0700 Subject: [PATCH 4/6] Refine Preview 4 aspnetcore notes after live validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live-tested every feature against the installed 11.0.100-preview.4.26224.122 build with reflection + sample apps: * Resolve TLS TODO: confirm ITlsHandshakeFeature.Exception property name. * OpenAPI file results: note .Produces() annotation is required for the binary schema to appear (PR #64562 fires from metadata, not auto-inference). * Endpoint filter on binding failure: drop the inaccurate ValueTask claim (PR #64539 applies to any return type), and call out RouteHandlerOptions.ThrowOnBadRequest = false so the filter observes the 400 in Development mode. Filed dotnet/aspnetcore#66541 for a Virtualize prepend edge case (scroll-anchor regression when `_itemsBefore == 0`); release-notes claim left as-is — the bug only affects the case where the user has not yet scrolled the rendered window past index 0. Circuit-pause and `mcpserver` template remain documented; both PRs were merged late in the cycle and are expected to land in a Preview 4 servicing build. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- release-notes/11.0/preview/preview4/aspnetcore.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/release-notes/11.0/preview/preview4/aspnetcore.md b/release-notes/11.0/preview/preview4/aspnetcore.md index 4901d836ca..dd6a17ff8b 100644 --- a/release-notes/11.0/preview/preview4/aspnetcore.md +++ b/release-notes/11.0/preview/preview4/aspnetcore.md @@ -111,12 +111,10 @@ Moving the template into ASP.NET Core makes it discoverable from `dotnet new lis Two related changes make it easier to diagnose and customize TLS connections in Kestrel. -`ITlsHandshakeFeature` now exposes the exception thrown during a failed TLS handshake, so middleware and logging can record why a connection failed instead of seeing a bare `IOException` further up the stack ([dotnet/aspnetcore #65807](https://github.com/dotnet/aspnetcore/pull/65807)). The feature continues to work after the handshake fails — Kestrel snapshots the relevant fields off the underlying `SslStream` before it is disposed. +`ITlsHandshakeFeature` now exposes an `Exception` property containing the exception thrown during a failed TLS handshake, so middleware and logging can record why a connection failed instead of seeing a bare `IOException` further up the stack ([dotnet/aspnetcore #65807](https://github.com/dotnet/aspnetcore/pull/65807)). The feature continues to work after the handshake fails — Kestrel snapshots the relevant fields off the underlying `SslStream` before it is disposed. The `TlsClientHelloBytesCallback` option on `HttpsConnectionAdapterOptions` was reworked as a connection middleware ([dotnet/aspnetcore #65808](https://github.com/dotnet/aspnetcore/pull/65808)). The previous callback shape is now obsolete; configure ClientHello inspection via the connection-builder pipeline instead. - - ## Response compression always emits `Vary: Accept-Encoding` The response-compression middleware now adds `Vary: Accept-Encoding` to every response when compression is enabled, even when the response itself isn't compressed ([dotnet/aspnetcore #55092](https://github.com/dotnet/aspnetcore/pull/55092)). This prevents shared caches and CDNs from serving a compressed payload to a client that didn't ask for one (or vice versa). @@ -127,8 +125,8 @@ Thank you [@pedrobsaila](https://github.com/pedrobsaila) for this contribution! Two changes round out the minimal API + OpenAPI experience this preview: -- **File result types appear in OpenAPI documents.** `FileStreamResult`, `FileContentHttpResult`, and `FileStreamHttpResult` are now described as binary string schemas in generated OpenAPI documents, so clients see accurate response shapes for endpoints that stream files ([dotnet/aspnetcore #64562](https://github.com/dotnet/aspnetcore/pull/64562)). Thank you [@marcominerva](https://github.com/marcominerva) for this contribution! -- **Endpoint filters can observe parameter-binding failures.** When a minimal API endpoint has filters configured and its delegate returns `ValueTask`, the filter pipeline now runs even if parameter binding fails. Filters can read the 400 response and substitute their own. Endpoints without filters continue to short-circuit with a 400 as before ([dotnet/aspnetcore #64539](https://github.com/dotnet/aspnetcore/pull/64539)). Thank you [@marcominerva](https://github.com/marcominerva) for this contribution! +- **File result types appear in OpenAPI documents.** `FileStreamResult`, `FileContentHttpResult`, and `FileStreamHttpResult` are now described as binary string schemas in generated OpenAPI documents, so clients see accurate response shapes for endpoints that stream files ([dotnet/aspnetcore #64562](https://github.com/dotnet/aspnetcore/pull/64562)). Annotate the endpoint with `.Produces(contentType: "application/pdf")` (or the equivalent `*StreamHttpResult`/`FileStreamResult` type) so OpenAPI sees the result type and emits the binary schema. Thank you [@marcominerva](https://github.com/marcominerva) for this contribution! +- **Endpoint filters can observe parameter-binding failures.** When a minimal API endpoint has any filters or filter factories configured, the filter pipeline now runs even if parameter binding fails. Filters can read `HttpContext.Response.StatusCode == 400` and substitute their own response body. Endpoints without filters continue to short-circuit with a 400 as before ([dotnet/aspnetcore #64539](https://github.com/dotnet/aspnetcore/pull/64539)). In Development, set `RouteHandlerOptions.ThrowOnBadRequest = false` so the framework returns a 400 the filter can observe instead of throwing `BadHttpRequestException` to the developer exception page. Thank you [@marcominerva](https://github.com/marcominerva) for this contribution! ## Smaller Blazor WebAssembly publish output From f23ff19d39720b15ea0a90dbf36edd4edb84ecec Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 30 Apr 2026 17:54:55 -0700 Subject: [PATCH 5/6] Address PR feedback: HTTP QUERY scope, Virtualize split, runtime-async * HTTP QUERY (#65714) is OpenAPI-only; reword and rename heading. * Virtualize: clarify #65951 covers height-changes-above-viewport (no API change). Add separate section for #66521's new AnchorMode parameter, including ItemComparer guidance for reference-type items. * Add a Runtime-async section for #66449 (backport of #66200). Removes the pre-filtering note that excluded it. Feedback from BrennanConroy and ilonatommy on dotnet/core#10389. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../11.0/preview/preview4/aspnetcore.md | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/release-notes/11.0/preview/preview4/aspnetcore.md b/release-notes/11.0/preview/preview4/aspnetcore.md index dd6a17ff8b..c35a0a38a8 100644 --- a/release-notes/11.0/preview/preview4/aspnetcore.md +++ b/release-notes/11.0/preview/preview4/aspnetcore.md @@ -2,16 +2,18 @@ .NET 11 Preview 4 includes new ASP.NET Core features and improvements: -- [Support for the HTTP QUERY method](#support-for-the-http-query-method) +- [HTTP QUERY in generated OpenAPI documents](#http-query-in-generated-openapi-documents) - [SupplyParameterFromTempData for Blazor](#supplyparameterfromtempdata-for-blazor) - [Server-initiated Blazor Server circuit pause](#server-initiated-blazor-server-circuit-pause) - [Virtualize keeps the viewport stable when content above it changes](#virtualize-keeps-the-viewport-stable-when-content-above-it-changes) +- [Virtualize AnchorMode for stable viewports during prepend and append](#virtualize-anchormode-for-stable-viewports-during-prepend-and-append) - [Blazor WebAssembly service defaults template](#blazor-webassembly-service-defaults-template) - [MCP Server template ships with the .NET SDK](#mcp-server-template-ships-with-the-net-sdk) - [TLS handshake observability in Kestrel](#tls-handshake-observability-in-kestrel) - [Response compression always emits `Vary: Accept-Encoding`](#response-compression-always-emits-vary-accept-encoding) - [OpenAPI and minimal API improvements](#openapi-and-minimal-api-improvements) - [Smaller Blazor WebAssembly publish output](#smaller-blazor-webassembly-publish-output) +- [Runtime-async enabled for shared framework libraries](#runtime-async-enabled-for-shared-framework-libraries) - [Breaking changes](#breaking-changes) - [Bug fixes](#bug-fixes) - [Community contributors](#community-contributors) @@ -20,9 +22,9 @@ ASP.NET Core updates in .NET 11: - [What's new in ASP.NET Core in .NET 11](https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-11) -## Support for the HTTP QUERY method +## HTTP QUERY in generated OpenAPI documents -ASP.NET Core now recognizes [HTTP QUERY](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/) as a first-class HTTP method in routing, minimal APIs, and OpenAPI document generation ([dotnet/aspnetcore #65714](https://github.com/dotnet/aspnetcore/pull/65714)). QUERY is a proposed safe, idempotent method that lets clients send a request body when describing a search — useful when a query is too large or too structured to fit in a URL. +OpenAPI document generation now recognizes [HTTP QUERY](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/) as a first-class operation type ([dotnet/aspnetcore #65714](https://github.com/dotnet/aspnetcore/pull/65714)). QUERY is a proposed safe, idempotent method that lets clients send a request body when describing a search — useful when a query is too large or too structured to fit in a URL. Routing already accepted arbitrary verb strings via `MapMethods`; this change makes QUERY endpoints show up correctly in the generated OpenAPI document so client generators and API explorers can consume them. ```csharp var app = WebApplication.Create(); @@ -33,6 +35,8 @@ app.MapMethods("/search", ["QUERY"], (SearchRequest request) => app.Run(); ``` +Thank you [@kilifu](https://github.com/kilifu) for this contribution! + The method shows up in generated OpenAPI documents alongside `GET`, `POST`, and friends, so client generators and API explorers pick it up automatically. Thank you [@kilifu](https://github.com/kilifu) for this contribution! @@ -79,9 +83,34 @@ The method returns `true` when the client was successfully asked to begin pausin ## Virtualize keeps the viewport stable when content above it changes -Preview 3 taught Blazor's `Virtualize` to handle items with different heights. Preview 4 builds on that with viewport stability: visible items stay in place when items above the viewport change height, and when items are prepended to the collection ([dotnet/aspnetcore #65951](https://github.com/dotnet/aspnetcore/pull/65951)). +Blazor's `Virtualize` no longer shifts visible content when items above the viewport change height ([dotnet/aspnetcore #65951](https://github.com/dotnet/aspnetcore/pull/65951)). Previously the component disabled the browser's native scroll anchoring (to avoid an infinite render loop) which meant any height change above the viewport — item expansion, data updates, lazy-loaded content — would cause visible items to jump on screen. + +The fix uses a hybrid approach: native CSS scroll anchoring on browsers that support it for non-`
` layouts, with a manual `ResizeObserver`-based scroll-compensation fallback for `
` layouts and Safari (where native anchoring miscalculates positions on `` candidates). Apps using `Virtualize` get this automatically — no API changes required. + +## Virtualize AnchorMode for stable viewports during prepend and append + +A new `AnchorMode` parameter on `Virtualize` controls viewport behavior at list edges when items are added dynamically — for chat UIs, news feeds, log viewers, and similar scenarios ([dotnet/aspnetcore #66521](https://github.com/dotnet/aspnetcore/pull/66521)). The component snapshots an anchor element before each render and restores its position after, so the visible items stay where the user is looking even when items are inserted before the current viewport (prepend) or after it (append). The mechanism works for both fixed- and variable-height items. + +```razor + + @msg.Text + + +@code { + private static readonly IEqualityComparer _messageById = + EqualityComparer.Create((a, b) => a?.Id == b?.Id, m => m.Id.GetHashCode()); +} +``` + +`AnchorMode` accepts: -The component uses native CSS scroll anchoring where the browser supports it and falls back to manual scroll compensation otherwise (notably for `
` layouts and Safari). Apps using `Virtualize` get this automatically — no API changes required. +- `VirtualizeAnchorMode.Beginning` — preserve viewport when items are prepended (auto-follow the bottom for chat-style UIs). +- `VirtualizeAnchorMode.End` — preserve viewport when items are appended. +- `VirtualizeAnchorMode.None` — no anchoring (default). + +For reference-type items, also supply an `ItemComparer` so the component can correlate items across renders. Without one, `Virtualize` falls back to `EqualityComparer.Default`, which uses reference equality for reference types and won't recognize a re-fetched item as the same logical entity. ## Blazor WebAssembly service defaults template @@ -137,6 +166,12 @@ Two trimming changes shrink published Blazor WebAssembly apps that don't use Ope Apps that use OpenTelemetry or hot reload aren't affected — the feature switches default on in those configurations. +## Runtime-async enabled for shared framework libraries + +ASP.NET Core's shared-framework-only libraries are now compiled with the `runtime-async` feature on `net11.0+` ([dotnet/aspnetcore #66449](https://github.com/dotnet/aspnetcore/pull/66449), backporting [#66200](https://github.com/dotnet/aspnetcore/pull/66200)). Runtime-async lets the runtime, rather than the C# compiler, generate the state machine for `async`/`await`, which can reduce per-await allocations and improve diagnostics. This is an internal codegen change with no public API impact — apps targeting `net11.0` automatically benefit when they call into the affected ASP.NET Core libraries. + +Libraries that ship as both shared-framework members and standalone NuGet packages are excluded, because runtime-async is incompatible with WebAssembly and would otherwise break wasm consumers of those packages. + ## Breaking changes - **`%2F` is preserved in HTTP/1.1 absolute-form request targets.** Previously, a request like `GET http://host/a%2Fb` was decoded to a path of `/a/b`, while `GET /a%2Fb` (origin-form) preserved the encoded slash. Both forms now resolve to `/a%2Fb`. Apps that depended on the inconsistent absolute-form behavior should update their routing or middleware to expect the encoded segment ([dotnet/aspnetcore #65930](https://github.com/dotnet/aspnetcore/pull/65930)). @@ -151,7 +186,6 @@ Apps that use OpenTelemetry or hot reload aren't affected — the feature switch - Razor editor/IDE fixes (#13017, #13023, #13035, #13043, #13044, #13057, #13063, #13065): tooling/IDE work — product-boundary rule excludes these from ASP.NET Core product notes. - "Detach methods when disconnection confirmed" (#66275) and resource-collection gzip footer (#66242): rolled into Bug fixes. - Blazor Web Worker template renames and clean-up (#66070, #66261): rolled into Bug fixes / templates section. - - Runtime-async enablement for SharedFx-only libraries (#66449): cross-stack runtime-async work; covered in the runtime release notes. - Numerous infra / dependency / loc / agentic-workflow / source-build PRs: pre-filtered (~69 entries) before scoring. --> From 30bc614224cbd7c0b5c3d1ebcf52945e80f084d3 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 30 Apr 2026 23:00:01 -0700 Subject: [PATCH 6/6] Add WebWorker import-map fingerprinting fix to Bug fixes Missed in initial pass: dotnet/aspnetcore#65885 fixes the Blazor Web Worker template failing in published WASM apps because workers don't inherit the page's import map. Belongs alongside the existing WebWorker template entries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- release-notes/11.0/preview/preview4/aspnetcore.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release-notes/11.0/preview/preview4/aspnetcore.md b/release-notes/11.0/preview/preview4/aspnetcore.md index c35a0a38a8..deaac816fc 100644 --- a/release-notes/11.0/preview/preview4/aspnetcore.md +++ b/release-notes/11.0/preview/preview4/aspnetcore.md @@ -195,6 +195,7 @@ Libraries that ship as both shared-framework members and standalone NuGet packag - Fixed an `InvalidOperationException` when navigating to `/Error` in newly scaffolded Blazor Server apps. The template now declares `RequestId` as `public` so `[PersistentState]` can read it ([dotnet/aspnetcore #66245](https://github.com/dotnet/aspnetcore/pull/66245)). - Fixed a truncated gzip payload for `resource-collection.js.gz` that caused some clients to reject the response. The endpoint now writes the gzip footer before serving the bytes ([dotnet/aspnetcore #66242](https://github.com/dotnet/aspnetcore/pull/66242)). - Fixed an "Interop methods are already registered for renderer 1" error when a Blazor Server reconnect fell back to resume after the original circuit had expired ([dotnet/aspnetcore #66275](https://github.com/dotnet/aspnetcore/pull/66275)). + - Fixed the Blazor Web Worker template failing in published Blazor WebAssembly apps. Workers don't inherit the page's import map, so fingerprinted `_framework/dotnet.js` couldn't be resolved from the worker context; the worker client now resolves the URL on the main thread via `import.meta.resolve()` and passes it to the worker through `postMessage` ([dotnet/aspnetcore #65885](https://github.com/dotnet/aspnetcore/pull/65885)). - **Routing** - Fixed `NegotiationMatcherPolicy` invalidating higher-priority endpoints when a lower-priority endpoint shared a DFA path node and carried `ContentEncodingMetadata`. Content-encoding negotiation now disambiguates only between representations of the same resource ([dotnet/aspnetcore #65973](https://github.com/dotnet/aspnetcore/pull/65973)). - **MVC**