From 004e0c26a274bdcb2a6e8f7ac1d00f4b5279a4d4 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 8 Jul 2026 10:57:17 +0200 Subject: [PATCH 1/7] Enhance MEV documentation --- .../fundamentals/minimal-apis/validation.md | 70 +++++++++++++++++++ .../includes/validation-package-net10.md | 27 ------- aspnetcore/mvc/models/validation.md | 4 -- aspnetcore/toc.yml | 2 + .../tutorials/first-mvc-app/validation.md | 2 - 5 files changed, 72 insertions(+), 33 deletions(-) create mode 100644 aspnetcore/fundamentals/minimal-apis/validation.md delete mode 100644 aspnetcore/includes/validation-package-net10.md diff --git a/aspnetcore/fundamentals/minimal-apis/validation.md b/aspnetcore/fundamentals/minimal-apis/validation.md new file mode 100644 index 000000000000..9018529fdb18 --- /dev/null +++ b/aspnetcore/fundamentals/minimal-apis/validation.md @@ -0,0 +1,70 @@ +--- +title: Validation in Minimal API apps +author: Youssef1313 +description: Use Microsoft.Extensions.Validation in Minimal API apps to validate API models. +ms.author: ygerges +ms.date: 07/08/2026 +monikerRange: '>= aspnetcore-10.0' +uid: fundamentals/minimal-apis/validation + +# customer intent: As an ASP.NET developer, I want to have automatic validation of models in Minimal API parameters. +--- + +# Validation in Minimal API apps + +In .NET 10, Microsoft.Extensions.Validation was introduced to support complex model validation. + +To enable validation, call `AddValidation` on the `IServiceCollection` instance in the web application entry point. + +```csharp +builder.Services.AddValidation(); +``` + +## Parameter validation + +Parameter validation is the first step in the validation pipeline in minimal API endpoints. It involves the following steps: + +1. Validate `ValidationAttribute`s applied to the minimal API parameter. +2. If the parameter type is `IEnumerable`, a type validation for all non-null elements happens. Otherwise, a single type validation for the parameter value happens. + +> [!NOTE] +> There is a known limitation currently that nullable value types declared as minimal API parameters don't get validated. +> For more information, see [dotnet/aspnetcore#67033](https://github.com/dotnet/aspnetcore/issues/67033). + +If the minimal API parameter type is `IEnumerable`, a type validation for all non-null elements happens. Otherwise, a single type validation for the value happens. + +## Type validation + +Type validation is the next step after parameter validation. It involves the following: + +1. Validate properties on the type. If any errors are found in this step, the validation stops here. +2. Validate type-level `ValidationAttribute`s. If any errors are found in this step, the validation stops here. +3. Validate `IValidatableObject`, if it's implemented. + +## Property validation + +Property validation happens as part of the type validation as explained in the previous section. It involves the following steps: + +1. Validate `ValidationAttribute`s applied on the property. +2. If the property value is `IEnumerable`, a type validation for all non-null elements happens. Otherwise, a single type validation for the value happens. + +## Explicit validation skipping + +When needed, you can skip validation for a specific parameter, type, or property by applying the `SkipValidationAttribute`. + +## Force-generate validatable type information + +The Microsoft.Extensions.Validation package works via a Roslyn source generator which detects the object graph and types for minimal API endpoint parameters. + +In some cases, not all types that will be part of the object graph can be determined at compile time. In these cases, you can force the source generator to consider a type for validation by applying `ValidatableTypeAttribute` to that type. + +## Async validation support + +Starting in .NET 11, Microsoft.Extensions.Validation supports async validation. You can apply custom implementations of `AsyncValidationAttribute` to parameters, types, or properties, and they will be called asynchronously. In addition, types can implement `IAsyncValidatableObject` as well. + +> [!IMPORTANT] +> Both `IAsyncValidatableObject` and `AsyncValidationAttribute` forces to implement the validation logic synchronously **and** asynchronously. +> For the case of minimal API validation using Microsoft.Extensions.Validation, we will always call the async path and never the sync path. +> The sync and async path are never intended to be both called together. If your implementation can't support the sync path, you can throw `InvalidOperationException`. + +When validating properties on a type, we start all validation tasks concurrently. Similarly, when we validate `IEnumerable`s, we start validation tasks for elements concurrently. \ No newline at end of file diff --git a/aspnetcore/includes/validation-package-net10.md b/aspnetcore/includes/validation-package-net10.md deleted file mode 100644 index dba852f7dab6..000000000000 --- a/aspnetcore/includes/validation-package-net10.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: .NET 10 validation package information -ai-usage: ai-assisted -ms.author: wpickett -ms.date: 08/28/2025 ---- - - -## Validation in .NET 10 - -In .NET 10, the unified validation APIs have been moved to the `Microsoft.Extensions.Validation` NuGet package. This change makes the validation APIs available outside of ASP.NET Core HTTP scenarios. - -To use the `Microsoft.Extensions.Validation` APIs: - -* Add the following package reference: - - ```xml - - ``` - - The functionality remains the same but now requires an explicit package reference. - -* Register validation services with dependency injection: - - ```csharp - builder.Services.AddValidation(); - ``` \ No newline at end of file diff --git a/aspnetcore/mvc/models/validation.md b/aspnetcore/mvc/models/validation.md index b23f10b7449b..2d224d5a17ce 100644 --- a/aspnetcore/mvc/models/validation.md +++ b/aspnetcore/mvc/models/validation.md @@ -18,10 +18,6 @@ This article explains how to validate user input in an ASP.NET Core MVC or Razor :::moniker-end -:::moniker range=">= aspnetcore-10.0" -[!INCLUDE[](~/includes/validation-package-net10.md)] -:::moniker-end - :::moniker range=">= aspnetcore-7.0" ## Model state diff --git a/aspnetcore/toc.yml b/aspnetcore/toc.yml index 0895dd74c2b2..90d1f97d75ca 100644 --- a/aspnetcore/toc.yml +++ b/aspnetcore/toc.yml @@ -1168,6 +1168,8 @@ items: uid: fundamentals/minimal-apis/responses - name: Filters uid: fundamentals/minimal-apis/min-api-filters + - name: Validation in minimal API apps + uid: fundamentals/minimal-apis/validation - name: Unit and integration tests uid: fundamentals/minimal-apis/test-min-api - name: Middleware diff --git a/aspnetcore/tutorials/first-mvc-app/validation.md b/aspnetcore/tutorials/first-mvc-app/validation.md index b789e8513a3a..6e6f9475f71b 100644 --- a/aspnetcore/tutorials/first-mvc-app/validation.md +++ b/aspnetcore/tutorials/first-mvc-app/validation.md @@ -26,8 +26,6 @@ One of the design tenets of MVC is [DRY](https://wikipedia.org/wiki/Don%27t_repe The validation support provided by MVC and Entity Framework Core is a good example of the DRY principle in action. You can declaratively specify validation rules in one place (in the model class) and the rules are enforced everywhere in the app. -[!INCLUDE[](~/includes/validation-package-net10.md)] - ## Delete the previously edited data In the next step, validation rules are added that don't allow null values. From 6b2daafa0aa536126ef2e5283874865cd13e50b5 Mon Sep 17 00:00:00 2001 From: Youssef Fahmy Date: Wed, 8 Jul 2026 21:54:56 +0200 Subject: [PATCH 2/7] Apply suggestions from code review Co-authored-by: Wade Pickett --- .../fundamentals/minimal-apis/validation.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/aspnetcore/fundamentals/minimal-apis/validation.md b/aspnetcore/fundamentals/minimal-apis/validation.md index 9018529fdb18..6632e98dbf68 100644 --- a/aspnetcore/fundamentals/minimal-apis/validation.md +++ b/aspnetcore/fundamentals/minimal-apis/validation.md @@ -25,7 +25,7 @@ builder.Services.AddValidation(); Parameter validation is the first step in the validation pipeline in minimal API endpoints. It involves the following steps: 1. Validate `ValidationAttribute`s applied to the minimal API parameter. -2. If the parameter type is `IEnumerable`, a type validation for all non-null elements happens. Otherwise, a single type validation for the parameter value happens. +1. If the parameter type is `IEnumerable`, validate the type for all non-null elements. Otherwise, validate the type for the value. > [!NOTE] > There is a known limitation currently that nullable value types declared as minimal API parameters don't get validated. @@ -35,18 +35,18 @@ If the minimal API parameter type is `IEnumerable`, a type validation for all no ## Type validation -Type validation is the next step after parameter validation. It involves the following: +Type validation is the next step after parameter validation. It involves the following steps: -1. Validate properties on the type. If any errors are found in this step, the validation stops here. -2. Validate type-level `ValidationAttribute`s. If any errors are found in this step, the validation stops here. -3. Validate `IValidatableObject`, if it's implemented. +1. Validate properties on the type. If any errors are found, the validation process stops. +1. Validate type-level `ValidationAttribute`s. If any errors are found, the validation process stops. +1. Validate `IValidatableObject`, if it's implemented. ## Property validation Property validation happens as part of the type validation as explained in the previous section. It involves the following steps: 1. Validate `ValidationAttribute`s applied on the property. -2. If the property value is `IEnumerable`, a type validation for all non-null elements happens. Otherwise, a single type validation for the value happens. +1. If the property value is `IEnumerable`, perform type validation for all non-null elements. Otherwise, perform a single type validation for the value. ## Explicit validation skipping @@ -54,7 +54,7 @@ When needed, you can skip validation for a specific parameter, type, or property ## Force-generate validatable type information -The Microsoft.Extensions.Validation package works via a Roslyn source generator which detects the object graph and types for minimal API endpoint parameters. +The Microsoft.Extensions.Validation package works via a Roslyn source generator that detects the object graph and types for minimal API endpoint parameters. In some cases, not all types that will be part of the object graph can be determined at compile time. In these cases, you can force the source generator to consider a type for validation by applying `ValidatableTypeAttribute` to that type. @@ -63,8 +63,8 @@ In some cases, not all types that will be part of the object graph can be determ Starting in .NET 11, Microsoft.Extensions.Validation supports async validation. You can apply custom implementations of `AsyncValidationAttribute` to parameters, types, or properties, and they will be called asynchronously. In addition, types can implement `IAsyncValidatableObject` as well. > [!IMPORTANT] -> Both `IAsyncValidatableObject` and `AsyncValidationAttribute` forces to implement the validation logic synchronously **and** asynchronously. -> For the case of minimal API validation using Microsoft.Extensions.Validation, we will always call the async path and never the sync path. -> The sync and async path are never intended to be both called together. If your implementation can't support the sync path, you can throw `InvalidOperationException`. +> Both `IAsyncValidatableObject` and `AsyncValidationAttribute` require you to implement the validation logic synchronously **and** asynchronously. +> For minimal API validation using `Microsoft.Extensions.Validation`, the framework always calls the async path and never the sync path. +> The sync and async paths are never intended to both be called together. If your implementation can't support the sync path, throw `InvalidOperationException`. When validating properties on a type, we start all validation tasks concurrently. Similarly, when we validate `IEnumerable`s, we start validation tasks for elements concurrently. \ No newline at end of file From b48b31bd71c3d5a079a7fc23ee79f781e7b016c4 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Thu, 9 Jul 2026 16:42:08 +0200 Subject: [PATCH 3/7] Move to generic overview --- aspnetcore/fundamentals/minimal-apis.md | 4 +++ aspnetcore/toc.yml | 5 +++ .../validation.md => validation/overview.md} | 33 +++++++++++++------ 3 files changed, 32 insertions(+), 10 deletions(-) rename aspnetcore/{fundamentals/minimal-apis/validation.md => validation/overview.md} (78%) diff --git a/aspnetcore/fundamentals/minimal-apis.md b/aspnetcore/fundamentals/minimal-apis.md index ba44f7fb59bb..2562a77b574b 100644 --- a/aspnetcore/fundamentals/minimal-apis.md +++ b/aspnetcore/fundamentals/minimal-apis.md @@ -299,6 +299,10 @@ See for more examples. For more information, see . +## Validation + +For more information, see . + ## Authorization Routes can be protected using authorization policies. These can be declared via the [`[Authorize]`](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) attribute or by using the method: diff --git a/aspnetcore/toc.yml b/aspnetcore/toc.yml index 90d1f97d75ca..b9a7ed232a41 100644 --- a/aspnetcore/toc.yml +++ b/aspnetcore/toc.yml @@ -1999,6 +1999,11 @@ items: - name: Directory structure displayName: deploy, publish uid: host-and-deploy/directory-structure + - name: Validation + displayName: validation + items: + - name: Overview + uid: validation/index - name: Security and Identity displayName: authentication, authorization items: diff --git a/aspnetcore/fundamentals/minimal-apis/validation.md b/aspnetcore/validation/overview.md similarity index 78% rename from aspnetcore/fundamentals/minimal-apis/validation.md rename to aspnetcore/validation/overview.md index 6632e98dbf68..26199f3ff03b 100644 --- a/aspnetcore/fundamentals/minimal-apis/validation.md +++ b/aspnetcore/validation/overview.md @@ -1,26 +1,39 @@ --- -title: Validation in Minimal API apps +title: Validation in ASP.NET Core author: Youssef1313 -description: Use Microsoft.Extensions.Validation in Minimal API apps to validate API models. +description: Use Microsoft.Extensions.Validation in ASP.NET Core to validate models. ms.author: ygerges -ms.date: 07/08/2026 +ms.date: 07/09/2026 monikerRange: '>= aspnetcore-10.0' -uid: fundamentals/minimal-apis/validation +uid: validation/index -# customer intent: As an ASP.NET developer, I want to have automatic validation of models in Minimal API parameters. +# customer intent: As an ASP.NET developer, I want to have automatic validation of models. --- -# Validation in Minimal API apps +# Validation in ASP.NET Core In .NET 10, Microsoft.Extensions.Validation was introduced to support complex model validation. +While the Microsoft.Extensions.Validation NuGet package can be used in scenarios outside ASP.NET Core, this article focuses on ASP.NET Core. + To enable validation, call `AddValidation` on the `IServiceCollection` instance in the web application entry point. ```csharp builder.Services.AddValidation(); ``` -## Parameter validation +> [!NOTE] +> ASP.NET Core has built-in support for Microsoft.Extensions.Validation for both minimal APIs and Blazor scenarios. It's not supported by default in MVC. + +## Validatable entities + +There are three types of entities that can be validated: + +- Parameters (specific to minimal API endpoint parameters) +- Types +- Properties + +### Parameter validation Parameter validation is the first step in the validation pipeline in minimal API endpoints. It involves the following steps: @@ -33,15 +46,15 @@ Parameter validation is the first step in the validation pipeline in minimal API If the minimal API parameter type is `IEnumerable`, a type validation for all non-null elements happens. Otherwise, a single type validation for the value happens. -## Type validation +### Type validation -Type validation is the next step after parameter validation. It involves the following steps: +Type validation is the next step after parameter validation (and is the first step in Blazor). It involves the following steps: 1. Validate properties on the type. If any errors are found, the validation process stops. 1. Validate type-level `ValidationAttribute`s. If any errors are found, the validation process stops. 1. Validate `IValidatableObject`, if it's implemented. -## Property validation +### Property validation Property validation happens as part of the type validation as explained in the previous section. It involves the following steps: From 887ea28c0498b78c7595bda0d6785ee34a799451 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Thu, 9 Jul 2026 16:45:09 +0200 Subject: [PATCH 4/7] Update toc --- aspnetcore/toc.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/aspnetcore/toc.yml b/aspnetcore/toc.yml index b9a7ed232a41..87e6b55d2b4c 100644 --- a/aspnetcore/toc.yml +++ b/aspnetcore/toc.yml @@ -1168,8 +1168,6 @@ items: uid: fundamentals/minimal-apis/responses - name: Filters uid: fundamentals/minimal-apis/min-api-filters - - name: Validation in minimal API apps - uid: fundamentals/minimal-apis/validation - name: Unit and integration tests uid: fundamentals/minimal-apis/test-min-api - name: Middleware From e410b5d6a5901afa208618e0ede3f872973e7f5a Mon Sep 17 00:00:00 2001 From: Youssef Fahmy Date: Thu, 9 Jul 2026 18:19:53 +0200 Subject: [PATCH 5/7] Apply suggestions from code review Co-authored-by: Wade Pickett --- aspnetcore/validation/overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnetcore/validation/overview.md b/aspnetcore/validation/overview.md index 26199f3ff03b..0905dfe24f8b 100644 --- a/aspnetcore/validation/overview.md +++ b/aspnetcore/validation/overview.md @@ -27,7 +27,7 @@ builder.Services.AddValidation(); ## Validatable entities -There are three types of entities that can be validated: +Three types of entities can be validated: - Parameters (specific to minimal API endpoint parameters) - Types @@ -41,7 +41,7 @@ Parameter validation is the first step in the validation pipeline in minimal API 1. If the parameter type is `IEnumerable`, validate the type for all non-null elements. Otherwise, validate the type for the value. > [!NOTE] -> There is a known limitation currently that nullable value types declared as minimal API parameters don't get validated. +> There's a known limitation where nullable value types declared as minimal API parameters aren't validated. > For more information, see [dotnet/aspnetcore#67033](https://github.com/dotnet/aspnetcore/issues/67033). If the minimal API parameter type is `IEnumerable`, a type validation for all non-null elements happens. Otherwise, a single type validation for the value happens. From 1930f23185f3b39c83224885803657d2248927d1 Mon Sep 17 00:00:00 2001 From: Youssef Fahmy Date: Thu, 9 Jul 2026 19:26:38 +0200 Subject: [PATCH 6/7] Apply suggestion from @wadepickett Co-authored-by: Wade Pickett --- aspnetcore/validation/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/validation/overview.md b/aspnetcore/validation/overview.md index 0905dfe24f8b..5e6bcd473ec1 100644 --- a/aspnetcore/validation/overview.md +++ b/aspnetcore/validation/overview.md @@ -69,7 +69,7 @@ When needed, you can skip validation for a specific parameter, type, or property The Microsoft.Extensions.Validation package works via a Roslyn source generator that detects the object graph and types for minimal API endpoint parameters. -In some cases, not all types that will be part of the object graph can be determined at compile time. In these cases, you can force the source generator to consider a type for validation by applying `ValidatableTypeAttribute` to that type. +In some cases, not all types that are part of the object graph can be determined at compile time. In these cases, you can force the source generator to consider a type for validation by applying `ValidatableTypeAttribute` to that type. ## Async validation support From 52d6913090dbfed147d3001d507e3a8b3f61fb35 Mon Sep 17 00:00:00 2001 From: Youssef Fahmy Date: Thu, 9 Jul 2026 19:27:05 +0200 Subject: [PATCH 7/7] Update overview.md --- aspnetcore/validation/overview.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/aspnetcore/validation/overview.md b/aspnetcore/validation/overview.md index 5e6bcd473ec1..f7c98249d16d 100644 --- a/aspnetcore/validation/overview.md +++ b/aspnetcore/validation/overview.md @@ -44,8 +44,6 @@ Parameter validation is the first step in the validation pipeline in minimal API > There's a known limitation where nullable value types declared as minimal API parameters aren't validated. > For more information, see [dotnet/aspnetcore#67033](https://github.com/dotnet/aspnetcore/issues/67033). -If the minimal API parameter type is `IEnumerable`, a type validation for all non-null elements happens. Otherwise, a single type validation for the value happens. - ### Type validation Type validation is the next step after parameter validation (and is the first step in Blazor). It involves the following steps: @@ -80,4 +78,4 @@ Starting in .NET 11, Microsoft.Extensions.Validation supports async validation. > For minimal API validation using `Microsoft.Extensions.Validation`, the framework always calls the async path and never the sync path. > The sync and async paths are never intended to both be called together. If your implementation can't support the sync path, throw `InvalidOperationException`. -When validating properties on a type, we start all validation tasks concurrently. Similarly, when we validate `IEnumerable`s, we start validation tasks for elements concurrently. \ No newline at end of file +When validating properties on a type, we start all validation tasks concurrently. Similarly, when we validate `IEnumerable`s, we start validation tasks for elements concurrently.