.NET 10 introduces a much cleaner and more streamlined way to handle API request validation. Instead of wiring up custom filters, manually checking ModelState, or relying on external libraries, the built-in validation pipeline now integrates directly with your endpoints. This means less boilerplate, more predictable behavior, and cleaner API contracts by default. In this post, we take a quick look at how easy it is to enable and use the new built-in validator in modern .NET APIs.
Request validation in ASP.NET APIs has traditionally required extra plumbing. Manual ModelState checks, custom filters, or third party libraries were common approaches to keep endpoints clean.
In .NET 10, validation is more tightly integrated into the request pipeline. Model binding and validation work together by default, reducing boilerplate and keeping endpoints focused on actual behavior.
Let’s look at a simple example.
using System.ComponentModel.DataAnnotations;
public sealed class CreateBlogPostRequest
{
[Required]
[MinLength(5)]
public string Title { get; init; } = string.Empty;
[Required]
[MinLength(20)]
public string Content { get; init; } = string.Empty;
[MaxLength(250)]
public string? Summary { get; init; }
[Required]
public Guid AuthorId { get; init; }
}
The contract defines its own constraints using standard DataAnnotations.
In .NET 10, Minimal APIs automatically trigger validation during model binding. If the request body violates any annotation, the framework returns a 400 Bad Request with a structured validation problem response.
app.MapPost("/api/blogposts", (CreateBlogPostRequest request) =>
{
return Results.Ok(new
{
Message = "Blog post created",
request.Title,
request.AuthorId
});
});
If a required field is missing or a constraint fails, the endpoint is never executed. The framework short-circuits the request before your business logic runs.
No manual ModelState checks. No guard clauses. No custom validation filters.
For more advanced scenarios, you can extend the pipeline using IValidatableObject when business rules require cross-property validation.
using System.ComponentModel.DataAnnotations;
public sealed class CreateBlogPostRequest : IValidatableObject
{
public string Title { get; init; } = string.Empty;
public string Content { get; init; } = string.Empty;
public Guid AuthorId { get; init; }
public IEnumerable<ValidationResult> Validate(ValidationContext context)
{
if (Title.StartsWith("Test") && Content.Length < 100)
{
yield return new ValidationResult(
"Posts starting with 'Test' must contain at least 100 characters of content.",
new[] { nameof(Content) });
}
}
}
This logic runs automatically as part of the same validation flow.
Validation is now a natural part of the request pipeline instead of something you wire up per endpoint.
Less boilerplate. Clearer intent. Predictable behavior.