ASP.NET Core cookbook · Beginner
Validate minimal API input with AddValidation
Handlers start with lines of manual `if` checks and return inconsistent error formats.
Approach
In .NET 10, AddValidation() validates minimal API parameters annotated with data annotations and returns
ValidationProblemDetails (400) before the handler runs. Input types must be public.
Solution
using System.ComponentModel.DataAnnotations;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddValidation();
builder.Services.AddProblemDetails();
var app = builder.Build();
app.MapPost("/api/bookings", (BookingRequest request) => TypedResults.Created($"/api/bookings/1", request));
app.MapGet("/api/bookings", ([Range(1, 100)] int pageSize = 20) => TypedResults.Ok(new { pageSize }));
app.Run();
public record BookingRequest(
[Required, EmailAddress] string Email,
[Range(1, 12)] int Guests,
[Required] DateOnly? Date) : IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext context)
{
if (Date < DateOnly.FromDateTime(DateTime.UtcNow))
yield return new ValidationResult("Date must be in the future", [nameof(Date)]);
}
}
Pitfalls
- Declaring request types
internal(the default for top-level types without a modifier is internal); the validation generator skips them. - Data annotations for rules that need the database (uniqueness); check those in the handler or service.
- Different error shapes per endpoint; ProblemDetails gives clients one format.
Variations
- Skip validation for an endpoint with
.DisableValidation(). - FluentValidation remains an option for complex rule sets, wired in with an endpoint filter.
Further reading: Minimal API validation
Reference: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis#validation
More ASP.NET Core recipes
- Accept file uploads with size and type limits
- Add OpenTelemetry traces and metrics
- Apply EF Core migrations safely during deployment
- Bind and validate options at startup
- Cache responses with output caching and evict by tag
- Call external APIs with typed HttpClients and resilience
- Configure CORS for a browser front end
- Expose liveness and readiness health checks