Skip to content

Commit 5079f30

Browse files
Copilotwadepickett
andauthored
What's New in ASP.NET Core in .NET 11 Preview 4 (#37135)
* Initial plan * Add What's New include files for ASP.NET Core .NET 11 Preview 4 Agent-Logs-Url: https://github.com/dotnet/AspNetCore.Docs/sessions/ffa52ac8-d279-4687-b95d-67b374819379 Co-authored-by: wadepickett <10985336+wadepickett@users.noreply.github.com> * Apply suggestion from @wadepickett * Apply suggestion from @wadepickett * Apply suggestion from @wadepickett --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: wadepickett <10985336+wadepickett@users.noreply.github.com> Co-authored-by: Wade Pickett <wpickett@microsoft.com>
1 parent 581c88a commit 5079f30

8 files changed

Lines changed: 138 additions & 1 deletion

aspnetcore/release-notes/aspnetcore-11.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ author: wadepickett
55
description: Learn about the new features in ASP.NET Core in .NET 11.
66
ms.author: wpickett
77
ms.custom: mvc
8-
ms.date: 03/13/2026
8+
ms.date: 05/12/2026
99
uid: aspnetcore-11
1010
---
1111
# What's new in ASP.NET Core in .NET 11
@@ -34,6 +34,8 @@ This section describes new features for SignalR.
3434

3535
This section describes new features for Minimal APIs.
3636

37+
[!INCLUDE[](~/release-notes/aspnetcore-11/includes/endpoint-filters-binding-failures-preview4.md)]
38+
3739
## OpenAPI
3840

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

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

47+
[!INCLUDE[](~/release-notes/aspnetcore-11/includes/http-query-openapi-preview4.md)]
48+
49+
[!INCLUDE[](~/release-notes/aspnetcore-11/includes/file-result-openapi-preview4.md)]
50+
4551
## Authentication and authorization
4652

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

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

75+
[!INCLUDE[](~/release-notes/aspnetcore-11/includes/mcp-server-template-preview4.md)]
76+
77+
[!INCLUDE[](~/release-notes/aspnetcore-11/includes/tls-handshake-observability-preview4.md)]
78+
79+
[!INCLUDE[](~/release-notes/aspnetcore-11/includes/response-compression-vary-header-preview4.md)]
80+
81+
[!INCLUDE[](~/release-notes/aspnetcore-11/includes/runtime-async-shared-framework-preview4.md)]
82+
6983
## Breaking changes
7084

7185
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.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
### Endpoint filters observe parameter-binding failures
2+
3+
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.
4+
5+
In the `Development` environment, set `RouteHandlerOptions.ThrowOnBadRequest = false` so the framework returns a 400 that 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.
6+
7+
Thank you [@marcominerva](https://github.com/marcominerva) for this contribution!
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
### File stream result types appear in OpenAPI documents
2+
3+
`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.
4+
5+
Thank you [@marcominerva](https://github.com/marcominerva) for this contribution!
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
### HTTP QUERY in generated OpenAPI documents
2+
3+
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.
4+
5+
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.
6+
7+
```csharp
8+
using Microsoft.OpenApi;
9+
10+
var builder = WebApplication.CreateBuilder(args);
11+
12+
builder.Services.AddOpenApi(options =>
13+
{
14+
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_2;
15+
});
16+
17+
var app = builder.Build();
18+
19+
app.MapOpenApi();
20+
21+
app.MapMethods("/search", ["QUERY"], (SearchRequest request) =>
22+
SearchService.Run(request));
23+
24+
app.Run();
25+
```
26+
27+
In an OpenAPI 3.2 document, the QUERY operation is described inline as a sibling of `get`, `post`, and other standard operations:
28+
29+
```json
30+
"paths": {
31+
"/search": {
32+
"query": {
33+
"requestBody": { ... },
34+
"responses": { "200": { ... } }
35+
}
36+
}
37+
}
38+
```
39+
40+
In OpenAPI 3.0 and 3.1 documents, the same operation is represented under the `x-oai-additionalOperations` extension on the Path Item:
41+
42+
```json
43+
"paths": {
44+
"/search": {
45+
"x-oai-additionalOperations": {
46+
"QUERY": {
47+
"requestBody": { ... },
48+
"responses": { "200": { ... } }
49+
}
50+
}
51+
}
52+
}
53+
```
54+
55+
Thank you [@kilifu](https://github.com/kilifu) for this contribution!
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
### MCP Server template ships with the .NET SDK
2+
3+
The `mcpserver` project template, previously available only by installing `Microsoft.McpServer.ProjectTemplates`, now ships as a bundled template in the .NET SDK:
4+
5+
```dotnetcli
6+
dotnet new mcpserver -o MyMcpServer
7+
```
8+
9+
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.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
### Response compression always emits `Vary: Accept-Encoding`
2+
3+
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).
4+
5+
Thank you [@pedrobsaila](https://github.com/pedrobsaila) for this contribution!
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
### Runtime-async enabled for shared framework libraries
2+
3+
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.
4+
5+
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.
6+
7+
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.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
### TLS handshake observability in Kestrel
2+
3+
Two related changes make it easier to diagnose and customize TLS connections in Kestrel.
4+
5+
`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.
6+
7+
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:
8+
9+
```csharp
10+
var builder = WebApplication.CreateBuilder(args);
11+
12+
builder.WebHost.ConfigureKestrel(options =>
13+
{
14+
options.ListenAnyIP(5001, listenOptions =>
15+
{
16+
listenOptions.Use(next => async context =>
17+
{
18+
await next(context);
19+
20+
var tlsHandshakeFeature = context.Features.Get<ITlsHandshakeFeature>();
21+
if (tlsHandshakeFeature?.Exception is { } ex)
22+
{
23+
Console.WriteLine($"[TLS Handshake Failed] ConnectionId={context.ConnectionId}, Exception={ex.GetType().Name}: {ex.Message}");
24+
}
25+
});
26+
27+
// UseTlsClientHelloListener must be called before UseHttps()
28+
listenOptions.UseTlsClientHelloListener((connection, clientHelloBytes) =>
29+
{
30+
Console.WriteLine($"TLS Client Hello received on {connection.ConnectionId}, {clientHelloBytes.Length} bytes");
31+
});
32+
listenOptions.UseHttps();
33+
});
34+
});
35+
```

0 commit comments

Comments
 (0)