From d5de904e06c892bf0fe3bfd48b24d4f5b9f5ec9d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Jul 2026 20:17:48 +0000 Subject: [PATCH 01/14] Initial plan From 9369471d0f758b7a7e6c51fc2e0d4fff881343cf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Jul 2026 20:22:35 +0000 Subject: [PATCH 02/14] Add What's New includes for ASP.NET Core .NET 11 Preview 6 --- aspnetcore/release-notes/aspnetcore-11.md | 12 ++++- ...async-validation-minimal-apis-preview-6.md | 49 +++++++++++++++++++ .../includes/csharp-unions-preview-6.md | 19 +++++-- .../includes/openapi-3-2-default-preview-6.md | 12 +++++ ...t-circuit-endpoints-attribute-preview-6.md | 26 ++++++++++ ...ignalr-authentication-refresh-preview-6.md | 45 +++++++++++++++++ ...ignalr-cancel-hub-invocations-preview-6.md | 22 +++++++++ 7 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md create mode 100644 aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md create mode 100644 aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md create mode 100644 aspnetcore/release-notes/aspnetcore-11/includes/signalr-authentication-refresh-preview-6.md create mode 100644 aspnetcore/release-notes/aspnetcore-11/includes/signalr-cancel-hub-invocations-preview-6.md diff --git a/aspnetcore/release-notes/aspnetcore-11.md b/aspnetcore/release-notes/aspnetcore-11.md index 8a5d11882b51..62b24fb950fe 100644 --- a/aspnetcore/release-notes/aspnetcore-11.md +++ b/aspnetcore/release-notes/aspnetcore-11.md @@ -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: 06/09/2026 +ms.date: 07/10/2026 uid: aspnetcore-11 --- # What's new in ASP.NET Core in .NET 11 @@ -30,6 +30,10 @@ This section describes new features for Blazor Hybrid. This section describes new features for SignalR. +[!INCLUDE[](~/release-notes/aspnetcore-11/includes/signalr-authentication-refresh-preview-6.md)] + +[!INCLUDE[](~/release-notes/aspnetcore-11/includes/signalr-cancel-hub-invocations-preview-6.md)] + ## Minimal APIs This section describes new features for Minimal APIs. @@ -38,6 +42,10 @@ This section describes new features for Minimal APIs. [!INCLUDE[](~/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md)] +[!INCLUDE[](~/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md)] + +[!INCLUDE[](~/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md)] + ## OpenAPI This section describes new features for OpenAPI. @@ -52,6 +60,8 @@ This section describes new features for OpenAPI. [!INCLUDE[](~/release-notes/aspnetcore-11/includes/openapi-schema-improvements-preview-5.md)] +[!INCLUDE[](~/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md)] + ## Authentication and authorization This section describes new features for authentication and authorization. diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md new file mode 100644 index 000000000000..0f7b19a2bdb1 --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md @@ -0,0 +1,49 @@ +### Async validation for minimal APIs + +Minimal API validation supports asynchronous validators end-to-end. The base libraries add the asynchronous DataAnnotations APIs `AsyncValidationAttribute`, `IAsyncValidatableObject`, and `Validator.ValidateObjectAsync`, and `Microsoft.Extensions.Validation` runs them when an endpoint validates a request. + + + +Asynchronous validation lets a validation rule do real work, such as a database lookup or a remote API call, without blocking a thread. A model implements `IAsyncValidatableObject` and returns validation results as an `IAsyncEnumerable`. Because `IAsyncValidatableObject` extends `IValidatableObject`, also implement the synchronous `Validate` method. When a type validates asynchronously only, throw from `Validate` so it isn't silently validated through the synchronous APIs: + +```csharp +using System.ComponentModel.DataAnnotations; +using System.Runtime.CompilerServices; + +public class ReservationRequest : IAsyncValidatableObject +{ + [Required] + public string Email { get; set; } = ""; + + public DateOnly Date { get; set; } + + // IValidatableObject (synchronous) — this type validates asynchronously only. + public IEnumerable Validate(ValidationContext context) => + throw new NotSupportedException("Validate this type with ValidateAsync."); + + public async IAsyncEnumerable ValidateAsync( + ValidationContext context, + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + var rooms = context.GetRequiredService(); + if (!await rooms.HasAvailabilityAsync(Date, cancellationToken)) + { + yield return new ValidationResult( + "No rooms are available on that date.", [nameof(Date)]); + } + } +} +``` + +Register validation and the framework validates the request before the endpoint runs: + +```csharp +builder.Services.AddValidation(); + +app.MapPost("/reservations", (ReservationRequest request) => + Results.Ok(request)); +``` + +Validators run concurrently where possible: asynchronous attributes on the same member start together, collection items validate in parallel, and the framework preserves the existing ordering between member, type, and `IValidatableObject` validation. For attribute-based rules, derive from `AsyncValidationAttribute` and override its `IsValidAsync` method. + +Thank you [@Youssef1313](https://github.com/Youssef1313) for the implementation work on this feature! diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md index 177e6a4fce50..200cb221c089 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md @@ -1,11 +1,22 @@ ### C# union types -ASP.NET Core supports [C# union types](/dotnet/csharp/whats-new/csharp-14#union-types) (new in .NET 11) anywhere [`System.Text.Json`](/dotnet/standard/serialization/system-text-json/overview) is used: JSON request and response bodies in Minimal APIs and MVC, SignalR's `JsonHubProtocol`, Blazor JavaScript interop, persistent component state, and prerendered component parameters. +C# union types are a preview language feature in .NET 11 (see the [C# release notes](/dotnet/csharp/whats-new/csharp-14#union-types)), and [`System.Text.Json`](/dotnet/standard/serialization/system-text-json/overview) serializes them natively. Because ASP.NET Core uses `System.Text.Json` for JSON, union types work as JSON request bodies and return types throughout the stack with no ASP.NET-specific configuration: + +* Minimal APIs — union body parameters and return types, including `Task`, `IAsyncEnumerable`, and `Results`, in both the runtime and source-generated request delegates. +* MVC and Razor Pages — union types as `[FromBody]` parameters and action or page-handler return types. +* SignalR — union types as hub method parameters, return values, and stream items when using the JSON hub protocol. +* Blazor — union types as component parameters, JS interop arguments and results, and persisted component state. ```csharp -public union UnionIntString(int, string); +// Requires preview +public record class Dog(string Name); +public record class Cat(int Lives); +public union Pet(Dog, Cat); -app.MapGet("/value", () => new UnionIntString(42)); +// The active case is serialized on the way out and described with anyOf in OpenAPI. +app.MapGet("/pets/{id}", Pet (int id) => id == 0 ? new Dog("Rex") : new Cat(9)); ``` -Union types aren't supported for non-body binding sources such as route values, query strings, headers, and form fields. \ No newline at end of file +For OpenAPI, an endpoint that returns a union is described with an `anyOf` schema listing each case type. Unlike polymorphic types, union cases don't carry a `$type` discriminator, so a case such as `Dog` reuses the standalone `#/components/schemas/Dog` component instead of a duplicated, prefixed one. ApiExplorer detects a union through `JsonTypeInfoKind.Union`, so the schema also flows through to Swashbuckle and NSwag. + +A few limits apply. Only JSON request bodies and responses are supported — binding a union from the query string, route values, headers, or form fields isn't yet available. When multiple cases serialize to the same JSON shape, disambiguate them with a `[JsonUnion]` classifier. SignalR unions require the JSON hub protocol; the MessagePack and Newtonsoft.Json protocols don't support unions. \ No newline at end of file diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md new file mode 100644 index 000000000000..456db68ef25a --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md @@ -0,0 +1,12 @@ +### OpenAPI 3.2 by default + +Generated OpenAPI documents now target OpenAPI 3.2 by default. OpenAPI 3.2 is the newest version of the specification. Documents continue to generate as before; set the document version explicitly if you need to target an earlier version for tooling that hasn't adopted 3.2 yet. + +To target an earlier version, specify it when calling : + +```csharp +builder.Services.AddOpenApi(options => +{ + options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_1; +}); +``` diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md new file mode 100644 index 000000000000..23467646d939 --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md @@ -0,0 +1,26 @@ +### Short-circuit endpoints with an attribute + +The new `[ShortCircuit]` attribute marks an endpoint to run immediately after routing, skipping the rest of the middleware pipeline. This is the attribute form of the existing `ShortCircuit()` endpoint convention, so it can be applied directly to MVC controllers and actions. + + + +Short-circuiting is useful for endpoints that don't need authentication, CORS, or other middleware — for example a health check or a robots.txt response — and it avoids the cost of running that middleware. The endpoint still runs and produces its response. Pass an optional status code, such as `[ShortCircuit(404)]`, to set the response status code. + +```csharp +[ApiController] +[Route("robots.txt")] +[ShortCircuit] +public class RobotsController : ControllerBase +{ + [HttpGet] + public IActionResult Get() => Content("User-agent: *\nDisallow:", "text/plain"); +} +``` + +The same attribute works on minimal API endpoints, and the existing `ShortCircuit()` convention continues to work unchanged: + +```csharp +app.MapGet("/health", [ShortCircuit] () => "Healthy"); +``` + +Thank you [@Porozhniakov](https://github.com/Porozhniakov) for contributing this feature! diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/signalr-authentication-refresh-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/signalr-authentication-refresh-preview-6.md new file mode 100644 index 000000000000..fea11296bcf8 --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-11/includes/signalr-authentication-refresh-preview-6.md @@ -0,0 +1,45 @@ +### SignalR authentication refresh + +SignalR connections can refresh authentication without dropping the connection when the access token expires. The server exposes a `/refresh` endpoint alongside `/negotiate` and reports the token lifetime in the negotiate response. The .NET client re-authenticates before the token expires, so a hub connection that previously closed when its bearer token aged out can stay open. This feature is implemented for the .NET client; the JavaScript/TypeScript client and Azure SignalR Service support are in progress. + + + +Enable the feature per hub on the server: + +```csharp +app.MapHub("/chat", options => +{ + options.EnableAuthenticationRefresh = true; + + // Optional: decide whether a given connection may refresh. + options.OnAuthenticationRefresh = context => ValueTask.FromResult(true); +}); +``` + +A hub can react to a refreshed identity by overriding `OnAuthenticationRefreshedAsync`: + +```csharp +public class ChatHub : Hub +{ + public override Task OnAuthenticationRefreshedAsync() + { + // The connection's User has been updated with the refreshed token. + return Task.CompletedTask; + } +} +``` + +Automatic refresh is on by default in the .NET client and is configurable with `WithAuthenticationRefresh`: + +```csharp +var connection = new HubConnectionBuilder() + .WithUrl("https://example.com/chat") + .WithAuthenticationRefresh(options => + { + // EnableAutoRefresh is true by default. + options.RefreshBeforeExpiration = TimeSpan.FromMinutes(1); + options.OnAuthenticationRefreshed = context => Task.CompletedTask; + options.OnAuthenticationRefreshFailed = context => Task.CompletedTask; + }) + .Build(); +``` diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/signalr-cancel-hub-invocations-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/signalr-cancel-hub-invocations-preview-6.md new file mode 100644 index 000000000000..06b7d5e7cc3c --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-11/includes/signalr-cancel-hub-invocations-preview-6.md @@ -0,0 +1,22 @@ +### Cancel hub invocations from the client + +The SignalR client can cancel a regular, non-streaming hub method invocation. Previously only streaming invocations could be canceled from the client. Now, when you pass a to and cancel it, the client sends a cancellation message and the hub method's `CancellationToken` parameter is triggered on the server. + +```csharp +// Client — canceling the token cancels the server-side invocation. +using var cts = new CancellationTokenSource(); +var work = connection.InvokeAsync("LongRunningWork", cts.Token); +// ... +cts.Cancel(); +``` + +```csharp +// Hub — accept a CancellationToken to observe client cancellation. +public class WorkHub : Hub +{ + public async Task LongRunningWork(CancellationToken cancellationToken) + { + await Task.Delay(TimeSpan.FromMinutes(5), cancellationToken); + } +} +``` From e4523cc9bf0d29caf7b02ca30d9da3a175d5cb82 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Fri, 10 Jul 2026 17:19:32 -0700 Subject: [PATCH 03/14] Apply suggestions from code review Edit pass. Co-authored-by: Wade Pickett --- .../aspnetcore-11/includes/csharp-unions-preview-6.md | 4 ++-- .../aspnetcore-11/includes/openapi-3-2-default-preview-6.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md index 200cb221c089..ec84db4b8751 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md @@ -5,10 +5,10 @@ C# union types are a preview language feature in .NET 11 (see the [C# release no * Minimal APIs — union body parameters and return types, including `Task`, `IAsyncEnumerable`, and `Results`, in both the runtime and source-generated request delegates. * MVC and Razor Pages — union types as `[FromBody]` parameters and action or page-handler return types. * SignalR — union types as hub method parameters, return values, and stream items when using the JSON hub protocol. -* Blazor — union types as component parameters, JS interop arguments and results, and persisted component state. +* Blazor — union types as component parameters, JavaScript interop arguments and results, and persisted component state. ```csharp -// Requires preview +// Requires preview in the project file. public record class Dog(string Name); public record class Cat(int Lives); public union Pet(Dog, Cat); diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md index 456db68ef25a..c1f05e630758 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md @@ -1,6 +1,6 @@ ### OpenAPI 3.2 by default -Generated OpenAPI documents now target OpenAPI 3.2 by default. OpenAPI 3.2 is the newest version of the specification. Documents continue to generate as before; set the document version explicitly if you need to target an earlier version for tooling that hasn't adopted 3.2 yet. +Generated OpenAPI documents now target OpenAPI 3.2 by default. Documents continue to generate as before; set the document version explicitly if you need to target an earlier version for tooling that hasn't adopted 3.2 yet. To target an earlier version, specify it when calling : From 8fac4356f35343f29e09cb41947d003edea456b2 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Tue, 14 Jul 2026 14:27:48 -0400 Subject: [PATCH 04/14] Apply suggestions from code review Co-authored-by: Luke Latham <1622880+guardrex@users.noreply.github.com> --- aspnetcore/release-notes/aspnetcore-11.md | 2 +- .../includes/async-validation-minimal-apis-preview-6.md | 3 ++- .../aspnetcore-11/includes/csharp-unions-preview-6.md | 2 +- .../aspnetcore-11/includes/openapi-3-2-default-preview-6.md | 2 +- .../includes/short-circuit-endpoints-attribute-preview-6.md | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/aspnetcore/release-notes/aspnetcore-11.md b/aspnetcore/release-notes/aspnetcore-11.md index 62b24fb950fe..91d3250e6fbb 100644 --- a/aspnetcore/release-notes/aspnetcore-11.md +++ b/aspnetcore/release-notes/aspnetcore-11.md @@ -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: 07/10/2026 +ms.date: 07/14/2026 uid: aspnetcore-11 --- # What's new in ASP.NET Core in .NET 11 diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md index 0f7b19a2bdb1..1f66992dc82a 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md @@ -4,7 +4,7 @@ Minimal API validation supports asynchronous validators end-to-end. The base lib -Asynchronous validation lets a validation rule do real work, such as a database lookup or a remote API call, without blocking a thread. A model implements `IAsyncValidatableObject` and returns validation results as an `IAsyncEnumerable`. Because `IAsyncValidatableObject` extends `IValidatableObject`, also implement the synchronous `Validate` method. When a type validates asynchronously only, throw from `Validate` so it isn't silently validated through the synchronous APIs: +Asynchronous validation lets a validation rule do real work, such as a database lookup or a remote API call, without blocking a thread. A model implements `IAsyncValidatableObject` and returns validation results as an `IAsyncEnumerable(); + if (!await rooms.HasAvailabilityAsync(Date, cancellationToken)) { yield return new ValidationResult( diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md index ec84db4b8751..7f9c52089cf4 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md @@ -19,4 +19,4 @@ app.MapGet("/pets/{id}", Pet (int id) => id == 0 ? new Dog("Rex") : new Cat(9)); For OpenAPI, an endpoint that returns a union is described with an `anyOf` schema listing each case type. Unlike polymorphic types, union cases don't carry a `$type` discriminator, so a case such as `Dog` reuses the standalone `#/components/schemas/Dog` component instead of a duplicated, prefixed one. ApiExplorer detects a union through `JsonTypeInfoKind.Union`, so the schema also flows through to Swashbuckle and NSwag. -A few limits apply. Only JSON request bodies and responses are supported — binding a union from the query string, route values, headers, or form fields isn't yet available. When multiple cases serialize to the same JSON shape, disambiguate them with a `[JsonUnion]` classifier. SignalR unions require the JSON hub protocol; the MessagePack and Newtonsoft.Json protocols don't support unions. \ No newline at end of file +A few limits apply. Only JSON request bodies and responses are supported—binding a union from the query string, route values, headers, or form fields isn't yet available. When multiple cases serialize to the same JSON shape, disambiguate them with a `[JsonUnion]` classifier. SignalR unions require the JSON hub protocol; the MessagePack and `Newtonsoft.Json` protocols don't support unions. \ No newline at end of file diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md index c1f05e630758..094d9ece47c3 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md @@ -1,6 +1,6 @@ ### OpenAPI 3.2 by default -Generated OpenAPI documents now target OpenAPI 3.2 by default. Documents continue to generate as before; set the document version explicitly if you need to target an earlier version for tooling that hasn't adopted 3.2 yet. +Generated OpenAPI documents now target OpenAPI 3.2 by default. Documents continue to generate as before. Set the document version explicitly if you need to target an earlier version for tooling that hasn't adopted 3.2 yet. To target an earlier version, specify it when calling : diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md index 23467646d939..3eb758965927 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md @@ -4,7 +4,7 @@ The new `[ShortCircuit]` attribute marks an endpoint to run immediately after ro -Short-circuiting is useful for endpoints that don't need authentication, CORS, or other middleware — for example a health check or a robots.txt response — and it avoids the cost of running that middleware. The endpoint still runs and produces its response. Pass an optional status code, such as `[ShortCircuit(404)]`, to set the response status code. +Short-circuiting is useful for endpoints that don't need authentication, CORS, or other middleware—for example a health check or a `robots.txt` response—and it avoids the cost of running that middleware. The endpoint still runs and produces its response. Pass an optional status code, such as `[ShortCircuit(404)]`, to set the response status code. ```csharp [ApiController] From b6a96dffb9d9a3bc879222f1e42612101c70518d Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Tue, 14 Jul 2026 14:29:18 -0400 Subject: [PATCH 05/14] Apply suggestions from code review Co-authored-by: Luke Latham <1622880+guardrex@users.noreply.github.com> --- .../aspnetcore-11/includes/csharp-unions-preview-6.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md index 7f9c52089cf4..74939c7a0750 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md @@ -1,6 +1,6 @@ ### C# union types -C# union types are a preview language feature in .NET 11 (see the [C# release notes](/dotnet/csharp/whats-new/csharp-14#union-types)), and [`System.Text.Json`](/dotnet/standard/serialization/system-text-json/overview) serializes them natively. Because ASP.NET Core uses `System.Text.Json` for JSON, union types work as JSON request bodies and return types throughout the stack with no ASP.NET-specific configuration: +C# union types are a preview language feature in .NET 11 (see the [C# release notes](/dotnet/csharp/whats-new/csharp-14#union-types) and [C# language reference](/dotnet/csharp/language-reference/builtin-types/union)), and [`System.Text.Json`](/dotnet/standard/serialization/system-text-json/overview) serializes them natively. Because ASP.NET Core uses `System.Text.Json` for JSON, union types work as JSON request bodies and return types throughout the stack with no ASP.NET-specific configuration: * Minimal APIs — union body parameters and return types, including `Task`, `IAsyncEnumerable`, and `Results`, in both the runtime and source-generated request delegates. * MVC and Razor Pages — union types as `[FromBody]` parameters and action or page-handler return types. From d145dc2dbcfac775a388514ea96c0b17276ba668 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Jul 2026 22:10:28 +0000 Subject: [PATCH 06/14] Give Blazor PR #37322 precedence in csharp-unions merge conflict --- .../includes/csharp-unions-preview-6.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md index 4097817555f0..e94b9227b1ac 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/csharp-unions-preview-6.md @@ -1,24 +1,15 @@ ### C# union types -C# union types are a preview language feature in .NET 11 (see the [C# release notes](/dotnet/csharp/whats-new/csharp-15#union-types) and [C# language reference](/dotnet/csharp/language-reference/builtin-types/union)), and [`System.Text.Json`](/dotnet/standard/serialization/system-text-json/overview) serializes them natively. Because ASP.NET Core uses `System.Text.Json` for JSON, union types work as JSON request bodies and return types throughout the stack with no ASP.NET-specific configuration: - -* Minimal APIs — union body parameters and return types, including `Task`, `IAsyncEnumerable`, and `Results`, in both the runtime and source-generated request delegates. -* MVC and Razor Pages — union types as `[FromBody]` parameters and action or page-handler return types. -* SignalR — union types as hub method parameters, return values, and stream items when using the JSON hub protocol. -* Blazor — union types as component parameters, JavaScript interop arguments and results, and persisted component state. +ASP.NET Core supports [C# union types](/dotnet/csharp/whats-new/csharp-15#union-types) ([C# language reference](/dotnet/csharp/language-reference/builtin-types/union)), which are new in .NET 11, anywhere [`System.Text.Json`](/dotnet/standard/serialization/system-text-json/overview) is used: JSON request and response bodies in Minimal APIs and MVC, SignalR's `JsonHubProtocol`, Blazor JavaScript interop, persistent component state, and prerendered component parameters. ```csharp -// Requires preview in the project file. -public record class Dog(string Name); -public record class Cat(int Lives); -public union Pet(Dog, Cat); +public union UnionIntString(int, string); -// The active case is serialized on the way out and described with anyOf in OpenAPI. -app.MapGet("/pets/{id}", Pet (int id) => id == 0 ? new Dog("Rex") : new Cat(9)); +app.MapGet("/value", () => new UnionIntString(42)); ``` -For OpenAPI, an endpoint that returns a union is described with an `anyOf` schema listing each case type. Unlike polymorphic types, union cases don't carry a `$type` discriminator, so a case such as `Dog` reuses the standalone `#/components/schemas/Dog` component instead of a duplicated, prefixed one. ApiExplorer detects a union through `JsonTypeInfoKind.Union`, so the schema also flows through to Swashbuckle and NSwag. +Union types aren't supported for non-body binding sources such as route values, query strings, headers, and form fields. -A few limits apply. Only JSON request bodies and responses are supported—binding a union from the query string, route values, headers, or form fields isn't yet available. When multiple cases serialize to the same JSON shape, disambiguate them with a `[JsonUnion]` classifier. SignalR unions require the JSON hub protocol; the MessagePack and `Newtonsoft.Json` protocols don't support unions. +For OpenAPI, an endpoint that returns a union is described with an `anyOf` schema listing each case type. Unlike polymorphic types, union cases don't carry a `$type` discriminator, so each case reuses its standalone component (for example, `#/components/schemas/Dog`) instead of a duplicated, prefixed one. ApiExplorer detects a union through `JsonTypeInfoKind.Union`, so the schema also flows through to Swashbuckle and NSwag. When multiple cases serialize to the same JSON shape, disambiguate them with a `[JsonUnion]` classifier. SignalR unions require the JSON hub protocol; the MessagePack and `Newtonsoft.Json` protocols don't support unions. For examples and additional information that apply to Blazor apps, see the [Component parameters section in the Components overview article](xref:blazor/components/index#component-parameters) and the [Pass parameters section of the Dynamically-rendered ASP.NET Core Razor components article](xref:blazor/components/dynamiccomponent). From 60d50194cfe0795327932f75c05deb81fb3cf0d8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Jul 2026 00:35:51 +0000 Subject: [PATCH 07/14] Add dotnet user-jwts file-based apps Preview 6 include --- aspnetcore/release-notes/aspnetcore-11.md | 4 +++- .../includes/user-jwts-file-based-apps-preview-6.md | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 aspnetcore/release-notes/aspnetcore-11/includes/user-jwts-file-based-apps-preview-6.md diff --git a/aspnetcore/release-notes/aspnetcore-11.md b/aspnetcore/release-notes/aspnetcore-11.md index 91d3250e6fbb..fa1dcaf263a1 100644 --- a/aspnetcore/release-notes/aspnetcore-11.md +++ b/aspnetcore/release-notes/aspnetcore-11.md @@ -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: 07/14/2026 +ms.date: 07/19/2026 uid: aspnetcore-11 --- # What's new in ASP.NET Core in .NET 11 @@ -70,6 +70,8 @@ This section describes new features for authentication and authorization. [!INCLUDE[](~/release-notes/aspnetcore-11/includes/infer-passkey-display-name-preview2.md)] +[!INCLUDE[](~/release-notes/aspnetcore-11/includes/user-jwts-file-based-apps-preview-6.md)] + ## Miscellaneous This section describes miscellaneous new features in .NET 11. diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/user-jwts-file-based-apps-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/user-jwts-file-based-apps-preview-6.md new file mode 100644 index 000000000000..5a8d63f84852 --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-11/includes/user-jwts-file-based-apps-preview-6.md @@ -0,0 +1,7 @@ +### `dotnet user-jwts` supports file-based apps + +The `dotnet user-jwts` tool creates signed development JWTs so you can call an app's authenticated endpoints without setting up a real identity provider. The `create` command generates a token, stores its signing key in the app's user secrets, and prints the token to use as a bearer token. It now works with file-based apps (a single `app.cs` with no project file) through the new `--file` option: + +```bash +dotnet user-jwts create --file app.cs +``` From 7be29062227acb50143d3ca32e6584ffc0abee61 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Sun, 19 Jul 2026 18:29:59 -0700 Subject: [PATCH 08/14] Apply suggestions from code review General edit by Wade Co-authored-by: Wade Pickett --- .../includes/async-validation-minimal-apis-preview-6.md | 2 +- .../aspnetcore-11/includes/openapi-3-2-default-preview-6.md | 2 +- .../includes/short-circuit-endpoints-attribute-preview-6.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md index 1f66992dc82a..3a965fdc9b7c 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md @@ -4,7 +4,7 @@ Minimal API validation supports asynchronous validators end-to-end. The base lib -Asynchronous validation lets a validation rule do real work, such as a database lookup or a remote API call, without blocking a thread. A model implements `IAsyncValidatableObject` and returns validation results as an `IAsyncEnumerable`. Because `IAsyncValidatableObject` extends `IValidatableObject`, also implement the synchronous `Validate` method. When a type validates asynchronously only, throw from `Validate` so it isn't silently validated through the synchronous APIs: ```csharp using System.ComponentModel.DataAnnotations; diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md index 094d9ece47c3..f75e8fa87528 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/openapi-3-2-default-preview-6.md @@ -1,6 +1,6 @@ ### OpenAPI 3.2 by default -Generated OpenAPI documents now target OpenAPI 3.2 by default. Documents continue to generate as before. Set the document version explicitly if you need to target an earlier version for tooling that hasn't adopted 3.2 yet. +Generated OpenAPI documents now target OpenAPI 3.2 by default. Documents continue to generate as before. Set the document version explicitly if you need to target an earlier version for tooling that doesn't yet support OpenAPI 3.2. To target an earlier version, specify it when calling : diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md index 3eb758965927..af13f1b18497 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/short-circuit-endpoints-attribute-preview-6.md @@ -4,7 +4,7 @@ The new `[ShortCircuit]` attribute marks an endpoint to run immediately after ro -Short-circuiting is useful for endpoints that don't need authentication, CORS, or other middleware—for example a health check or a `robots.txt` response—and it avoids the cost of running that middleware. The endpoint still runs and produces its response. Pass an optional status code, such as `[ShortCircuit(404)]`, to set the response status code. +Short-circuiting is useful for endpoints that don't need authentication, CORS, or other middleware—for example a health check or a `robots.txt` response, and it avoids the cost of running that middleware. The endpoint still runs and produces its response. Pass an optional status code, such as `[ShortCircuit(404)]`, to set the response status code. ```csharp [ApiController] From f08ee9c5625baba8d37036f33a368c94359f70bb Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Sun, 19 Jul 2026 21:16:41 -0700 Subject: [PATCH 09/14] Apply suggestions from code review Apply tdykstra review suggestions. Co-authored-by: Tom Dykstra --- .../includes/signalr-authentication-refresh-preview-6.md | 2 +- .../includes/signalr-cancel-hub-invocations-preview-6.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/signalr-authentication-refresh-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/signalr-authentication-refresh-preview-6.md index fea11296bcf8..88300301494d 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/signalr-authentication-refresh-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/signalr-authentication-refresh-preview-6.md @@ -11,7 +11,7 @@ app.MapHub("/chat", options => { options.EnableAuthenticationRefresh = true; - // Optional: decide whether a given connection may refresh. + // Optional: decide whether a given connection can refresh. options.OnAuthenticationRefresh = context => ValueTask.FromResult(true); }); ``` diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/signalr-cancel-hub-invocations-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/signalr-cancel-hub-invocations-preview-6.md index 06b7d5e7cc3c..91835b6a16ca 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/signalr-cancel-hub-invocations-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/signalr-cancel-hub-invocations-preview-6.md @@ -1,6 +1,6 @@ ### Cancel hub invocations from the client -The SignalR client can cancel a regular, non-streaming hub method invocation. Previously only streaming invocations could be canceled from the client. Now, when you pass a to and cancel it, the client sends a cancellation message and the hub method's `CancellationToken` parameter is triggered on the server. +The SignalR client can cancel a regular, non-streaming hub method invocation. Previously only streaming invocations could be canceled from the client. Now, when you pass a to and cancel it, the client sends a cancellation message, and the hub method's `CancellationToken` parameter is triggered on the server. ```csharp // Client — canceling the token cancels the server-side invocation. From 3fea3c4426277a98a3f391feefefce499a0d7df3 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Sun, 19 Jul 2026 21:41:52 -0700 Subject: [PATCH 10/14] Update async validation documentation for minimal APIs Enhance async validation support in minimal APIs with new DataAnnotations APIs. Update documentation to reflect changes in validation behavior and implementation examples. --- ...async-validation-minimal-apis-preview-6.md | 41 +++++++++++++++---- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md index 3a965fdc9b7c..0e4bc47b7b4f 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md @@ -1,10 +1,36 @@ ### Async validation for minimal APIs -Minimal API validation supports asynchronous validators end-to-end. The base libraries add the asynchronous DataAnnotations APIs `AsyncValidationAttribute`, `IAsyncValidatableObject`, and `Validator.ValidateObjectAsync`, and `Microsoft.Extensions.Validation` runs them when an endpoint validates a request. +Minimal API validation now supports asynchronous validators end-to-end ([dotnet/aspnetcore #66487](https://github.com/dotnet/aspnetcore/pull/66487), [dotnet/aspnetcore #67183](https://github.com/dotnet/aspnetcore/pull/67183)). Preview 5 shipped the building blocks for asynchronous form validation in Blazor. Preview 6 adds new asynchronous `DataAnnotations` APIs in the base libraries (`AsyncValidationAttribute` and `IAsyncValidatableObject`), and `Microsoft.Extensions.Validation` now runs them when an endpoint validates a request. The full set of new base-library APIs, including `Validator.ValidateObjectAsync`, is covered in the [.NET libraries release notes](./libraries.md#asynchronous-validation-with-dataannotations). - +The simplest way to add an asynchronous rule is a custom validation attribute. Derive from `AsyncValidationAttribute` and implement `IsValidAsync` to query a database or call a remote API without blocking a thread. The synchronous `IsValid` is abstract too; throw from it when the attribute validates asynchronously only: -Asynchronous validation lets a validation rule do real work, such as a database lookup or a remote API call, without blocking a thread. A model implements `IAsyncValidatableObject` and returns validation results as an `IAsyncEnumerable`. Because `IAsyncValidatableObject` extends `IValidatableObject`, also implement the synchronous `Validate` method. When a type validates asynchronously only, throw from `Validate` so it isn't silently validated through the synchronous APIs: +```csharp +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.DependencyInjection; + +public sealed class UniqueEmailAttribute : AsyncValidationAttribute +{ + // Synchronous IsValid. This attribute validates asynchronously only. + protected override ValidationResult? IsValid(object? value, ValidationContext context) => + throw new InvalidOperationException("Validate this attribute with IsValidAsync."); + + protected override async Task IsValidAsync( + object? value, ValidationContext context, CancellationToken cancellationToken) + { + var users = context.GetRequiredService(); + if (value is string email && await users.EmailExistsAsync(email, cancellationToken)) + { + return new ValidationResult("That email is already registered."); + } + + return ValidationResult.Success; + } +} +``` + +Apply `[UniqueEmail]` to a property like any built-in validation attribute. + +For validation that spans several properties or the whole object, implement `IAsyncValidatableObject` and return results as an `IAsyncEnumerable`. Because `IAsyncValidatableObject` extends `IValidatableObject`, also implement the synchronous `Validate` method. When a type validates asynchronously only, throw from `Validate` so its validation isn't silently skipped by the synchronous APIs: ```csharp using System.ComponentModel.DataAnnotations; @@ -17,16 +43,15 @@ public class ReservationRequest : IAsyncValidatableObject public DateOnly Date { get; set; } - // IValidatableObject (synchronous) — this type validates asynchronously only. + // Synchronous IValidatableObject. This type validates asynchronously only. public IEnumerable Validate(ValidationContext context) => - throw new NotSupportedException("Validate this type with ValidateAsync."); + throw new InvalidOperationException("Validate this type with ValidateAsync."); public async IAsyncEnumerable ValidateAsync( ValidationContext context, [EnumeratorCancellation] CancellationToken cancellationToken = default) { var rooms = context.GetRequiredService(); - if (!await rooms.HasAvailabilityAsync(Date, cancellationToken)) { yield return new ValidationResult( @@ -45,6 +70,4 @@ app.MapPost("/reservations", (ReservationRequest request) => Results.Ok(request)); ``` -Validators run concurrently where possible: asynchronous attributes on the same member start together, collection items validate in parallel, and the framework preserves the existing ordering between member, type, and `IValidatableObject` validation. For attribute-based rules, derive from `AsyncValidationAttribute` and override its `IsValidAsync` method. - -Thank you [@Youssef1313](https://github.com/Youssef1313) for the implementation work on this feature! +Validators run concurrently where possible: asynchronous attributes on the same member start together, collection items validate in parallel, and the framework preserves the existing ordering between member, type, and `IValidatableObject` validation. From cfeb01125e0c3ded888197a0a2c6b0612cbddf87 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Sun, 19 Jul 2026 21:42:36 -0700 Subject: [PATCH 11/14] Apply suggestion from @wadepickett --- .../includes/async-validation-minimal-apis-preview-6.md | 1 + 1 file changed, 1 insertion(+) diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md index 0e4bc47b7b4f..a422996130fb 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md @@ -18,6 +18,7 @@ public sealed class UniqueEmailAttribute : AsyncValidationAttribute object? value, ValidationContext context, CancellationToken cancellationToken) { var users = context.GetRequiredService(); + if (value is string email && await users.EmailExistsAsync(email, cancellationToken)) { return new ValidationResult("That email is already registered."); From 7e4644f384f7fa881aeb1ac744b345c9a290b637 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Sun, 19 Jul 2026 21:44:17 -0700 Subject: [PATCH 12/14] Implement room availability check in validation Added a check for room availability in validation. --- .../includes/async-validation-minimal-apis-preview-6.md | 1 + 1 file changed, 1 insertion(+) diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md index a422996130fb..4f6ef228f002 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md @@ -53,6 +53,7 @@ public class ReservationRequest : IAsyncValidatableObject [EnumeratorCancellation] CancellationToken cancellationToken = default) { var rooms = context.GetRequiredService(); + if (!await rooms.HasAvailabilityAsync(Date, cancellationToken)) { yield return new ValidationResult( From 7f664b2fe885f03e82fe7e498de0bf0a17269d98 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Sun, 19 Jul 2026 22:36:23 -0700 Subject: [PATCH 13/14] Update async-validation-minimal-apis-preview-6.md Fixed library link. --- .../includes/async-validation-minimal-apis-preview-6.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md index 4f6ef228f002..3f933ec32e27 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md @@ -1,6 +1,6 @@ ### Async validation for minimal APIs -Minimal API validation now supports asynchronous validators end-to-end ([dotnet/aspnetcore #66487](https://github.com/dotnet/aspnetcore/pull/66487), [dotnet/aspnetcore #67183](https://github.com/dotnet/aspnetcore/pull/67183)). Preview 5 shipped the building blocks for asynchronous form validation in Blazor. Preview 6 adds new asynchronous `DataAnnotations` APIs in the base libraries (`AsyncValidationAttribute` and `IAsyncValidatableObject`), and `Microsoft.Extensions.Validation` now runs them when an endpoint validates a request. The full set of new base-library APIs, including `Validator.ValidateObjectAsync`, is covered in the [.NET libraries release notes](./libraries.md#asynchronous-validation-with-dataannotations). +Minimal API validation now supports asynchronous validators end-to-end ([dotnet/aspnetcore #66487](https://github.com/dotnet/aspnetcore/pull/66487), [dotnet/aspnetcore #67183](https://github.com/dotnet/aspnetcore/pull/67183)). Preview 5 shipped the building blocks for asynchronous form validation in Blazor. Preview 6 adds new asynchronous `DataAnnotations` APIs in the base libraries (`AsyncValidationAttribute` and `IAsyncValidatableObject`), and `Microsoft.Extensions.Validation` now runs them when an endpoint validates a request. The full set of new base-library APIs, including `Validator.ValidateObjectAsync`, is covered in the [.NET libraries release notes](dotnet/core/release-notes/11.0/preview/preview6//libraries.md#asynchronous-validation-with-dataannotations). The simplest way to add an asynchronous rule is a custom validation attribute. Derive from `AsyncValidationAttribute` and implement `IsValidAsync` to query a database or call a remote API without blocking a thread. The synchronous `IsValid` is abstract too; throw from it when the attribute validates asynchronously only: From 206a4ec697f4d6107341978cc0b0e32eb6b96fa9 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Sun, 19 Jul 2026 22:52:29 -0700 Subject: [PATCH 14/14] Apply suggestion from @wadepickett Removed reference circling back to the release notes. --- .../includes/async-validation-minimal-apis-preview-6.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md index 3f933ec32e27..43d90a70feb8 100644 --- a/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md +++ b/aspnetcore/release-notes/aspnetcore-11/includes/async-validation-minimal-apis-preview-6.md @@ -1,6 +1,6 @@ ### Async validation for minimal APIs -Minimal API validation now supports asynchronous validators end-to-end ([dotnet/aspnetcore #66487](https://github.com/dotnet/aspnetcore/pull/66487), [dotnet/aspnetcore #67183](https://github.com/dotnet/aspnetcore/pull/67183)). Preview 5 shipped the building blocks for asynchronous form validation in Blazor. Preview 6 adds new asynchronous `DataAnnotations` APIs in the base libraries (`AsyncValidationAttribute` and `IAsyncValidatableObject`), and `Microsoft.Extensions.Validation` now runs them when an endpoint validates a request. The full set of new base-library APIs, including `Validator.ValidateObjectAsync`, is covered in the [.NET libraries release notes](dotnet/core/release-notes/11.0/preview/preview6//libraries.md#asynchronous-validation-with-dataannotations). +Minimal API validation now supports asynchronous validators end-to-end ([dotnet/aspnetcore #66487](https://github.com/dotnet/aspnetcore/pull/66487), [dotnet/aspnetcore #67183](https://github.com/dotnet/aspnetcore/pull/67183)). Preview 5 shipped the building blocks for asynchronous form validation in Blazor. Preview 6 adds new asynchronous `DataAnnotations` APIs in the base libraries (`AsyncValidationAttribute` and `IAsyncValidatableObject`), and `Microsoft.Extensions.Validation` now runs them when an endpoint validates a request. The simplest way to add an asynchronous rule is a custom validation attribute. Derive from `AsyncValidationAttribute` and implement `IsValidAsync` to query a database or call a remote API without blocking a thread. The synchronous `IsValid` is abstract too; throw from it when the attribute validates asynchronously only: