Minimal APIs have always made the happy path look good.
The unhappy path took more work. You could decorate a request model with Data Annotations, but nothing automatically validated it. Most of us wrote an endpoint filter, pulled in another package, or checked every property by hand.
ASP.NET Core 10 adds validation directly to Minimal APIs.
Try It
Create a .NET 10 empty web app:
dotnet new web -n MinimalValidationDemo -f net10.0cd MinimalValidationDemoReplace Program.cs with this:
using System.ComponentModel.DataAnnotations;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddValidation();
var app = builder.Build();
app.MapPost("/products", (CreateProduct request) =>{ var product = new Product( Id: Random.Shared.Next(1, 10_000), request.Name, request.Quantity);
return TypedResults.Created($"/products/{product.Id}", product);});
app.Run();
public sealed record CreateProduct( [Required, StringLength(100, MinimumLength = 3)] string Name,
[Range(1, 1_000)] int Quantity);
public sealed record Product(int Id, string Name, int Quantity);Run it:
dotnet runSend an invalid request:
curl -i -X POST http://localhost:5000/products -H "Content-Type: application/json" -d "{\"name\":\"\",\"quantity\":0}"Use the HTTP URL shown by dotnet run if your port is different. ASP.NET Core returns 400 Bad Request before your handler runs.
Send a valid request:
curl -i -X POST http://localhost:5000/products -H "Content-Type: application/json" -d "{\"name\":\"Mechanical Keyboard\",\"quantity\":4}"Validation Isn’t Limited to Request Bodies
The generated validation filter can validate values from the request body, query string, and headers:
app.MapGet("/inventory", ( [Range(1, 100)] int pageSize, [Required] string warehouse) =>{ return TypedResults.Ok(new { pageSize, warehouse });});The Multi-Assembly Gotcha
AddValidation() uses a source generator. It discovers validatable endpoint types in the assembly where you call it.
If your endpoints live in a separate class library, call AddValidation() from that assembly. Otherwise your attributes can look correct while the generated validation metadata never sees them.
You can disable validation for a specific endpoint with .DisableValidation(), but use that on purpose. Turning it off because a model is inconvenient usually means the model needs another look.
Key Takeaway
ASP.NET Core 10 can validate Minimal API inputs before your handler runs. Add AddValidation(), decorate the model you already have, and let the framework produce the 400 response.