Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion aspnetcore/release-notes/aspnetcore-11.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ author: wadepickett
description: Learn about the new features in ASP.NET Core in .NET 11.
ms.author: wpickett
ms.custom: mvc
ms.date: 03/13/2026
ms.date: 05/12/2026
uid: aspnetcore-11
---
# What's new in ASP.NET Core in .NET 11
Expand Down Expand Up @@ -34,6 +34,8 @@ This section describes new features for SignalR.

This section describes new features for Minimal APIs.

[!INCLUDE[](~/release-notes/aspnetcore-11/includes/endpoint-filters-binding-failures-preview4.md)]

## OpenAPI

This section describes new features for OpenAPI.
Expand All @@ -42,6 +44,10 @@ This section describes new features for OpenAPI.

[!INCLUDE[](~/release-notes/aspnetcore-11/includes/openapi-3-2-support-preview2.md)]

[!INCLUDE[](~/release-notes/aspnetcore-11/includes/http-query-openapi-preview4.md)]

[!INCLUDE[](~/release-notes/aspnetcore-11/includes/file-result-openapi-preview4.md)]

## Authentication and authorization

This section describes new features for authentication and authorization.
Expand All @@ -66,6 +72,14 @@ This section describes miscellaneous new features in .NET 11.

[!INCLUDE[](~/release-notes/aspnetcore-11/includes/http3-early-request-processing-preview-3.md)]

[!INCLUDE[](~/release-notes/aspnetcore-11/includes/mcp-server-template-preview4.md)]

[!INCLUDE[](~/release-notes/aspnetcore-11/includes/tls-handshake-observability-preview4.md)]

[!INCLUDE[](~/release-notes/aspnetcore-11/includes/response-compression-vary-header-preview4.md)]

[!INCLUDE[](~/release-notes/aspnetcore-11/includes/runtime-async-shared-framework-preview4.md)]

## Breaking changes

Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### Endpoint filters 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.

In the `Development` environment, set `RouteHandlerOptions.ThrowOnBadRequest = false` so the framework returns a 400 the filter can observe instead of throwing <xref:Microsoft.AspNetCore.Http.BadHttpRequestException> to the developer exception page. This is already the default in non-`Development` environments.
Comment thread
wadepickett marked this conversation as resolved.
Outdated

Thank you [@marcominerva](https://github.com/marcominerva) for this contribution!
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### File stream 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. Annotate the endpoint with `.Produces<FileContentHttpResult>(contentType: "application/pdf")` (or the equivalent `FileStreamHttpResult`/`FileStreamResult` type) so OpenAPI sees the result type and emits the binary schema.

Thank you [@marcominerva](https://github.com/marcominerva) for this contribution!
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
### HTTP QUERY in generated OpenAPI documents

OpenAPI document generation now recognizes [HTTP QUERY](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/) as a known operation type. 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 accepts arbitrary verb strings via `MapMethods`, and OpenAPI 3.2 adds a [`query` field to the Path Item Object](https://spec.openapis.org/oas/v3.2.0.html#fixed-fields-6) so this can be described in the OpenAPI document.

Note that `query` is only valid in an OpenAPI 3.2 document, so set the `OpenApiVersion` in the `OpenApiOptions`. In earlier OpenAPI versions, the `query` operation is generated within an `x-oai-additionalOperations` specification extension in the Path Item Object.

```csharp
using Microsoft.OpenApi;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi(options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_2;
});

var app = builder.Build();

app.MapOpenApi();

app.MapMethods("/search", ["QUERY"], (SearchRequest request) =>
SearchService.Run(request));

app.Run();
```

In an OpenAPI 3.2 document, the QUERY operation is described inline as a sibling of `get`, `post`, and friends:
Comment thread
wadepickett marked this conversation as resolved.
Outdated

```json
"paths": {
"/search": {
"query": {
"requestBody": { ... },
"responses": { "200": { ... } }
}
}
}
```

In OpenAPI 3.0 and 3.1 documents, the same operation is represented under the `x-oai-additionalOperations` extension on the Path Item:

```json
"paths": {
"/search": {
"x-oai-additionalOperations": {
"QUERY": {
"requestBody": { ... },
"responses": { "200": { ... } }
}
}
}
}
```

Thank you [@kilifu](https://github.com/kilifu) for this contribution!
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
### 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:

```dotnetcli
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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### 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. 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!
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### 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+`. 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.

Because runtime-async changes how `async`/`await` is generated for a large portion of the ASP.NET Core stack, try your apps against this preview and [file an issue](https://github.com/dotnet/aspnetcore/issues/new/choose) if you hit unexpected behavior, particularly around exception stacks, `ExecutionContext`/`AsyncLocal` flow, or anything that looks like a regression from .NET 10.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
### TLS handshake observability in Kestrel

Two related changes make it easier to diagnose and customize TLS connections in Kestrel.

`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. 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. The previous callback shape is now obsolete; configure ClientHello inspection via the new `ListenOptions.UseTlsClientHelloListener` extension instead. The example below uses both features together — connection middleware reads `ITlsHandshakeFeature.Exception` after the handshake, and `UseTlsClientHelloListener` inspects the ClientHello before TLS:

```csharp
var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(options =>
{
options.ListenAnyIP(5001, listenOptions =>
{
listenOptions.Use(next => async context =>
{
await next(context);

var tlsHandshakeFeature = context.Features.Get<ITlsHandshakeFeature>();
if (tlsHandshakeFeature?.Exception is { } ex)
{
Console.WriteLine($"[TLS Handshake Failed] ConnectionId={context.ConnectionId}, Exception={ex.GetType().Name}: {ex.Message}");
}
});

// UseTlsClientHelloListener must be called before UseHttps()
listenOptions.UseTlsClientHelloListener((connection, clientHelloBytes) =>
{
Console.WriteLine($"TLS Client Hello received on {connection.ConnectionId}, {clientHelloBytes.Length} bytes");
});
listenOptions.UseHttps();
});
});
```
Loading