.NET 10 Makes Minimal API Validation Super Simple
From tedious manual checks to built-in validation with a single line of code
.NET 10 is right around the corner, and this release finally makes validation in Minimal APIs very easy.
No more repetitive null checks or messy conditionals. One line of setup, a few attributes, and you’re done.
But before we get to the new way, let’s look at how it used to work.
The old way: manual validation
Before .NET 10, if you wanted to validate data in Minimal APIs, you had to handle it inside each endpoint.
Here’s what a typical POST endpoint looked like:
app.MapPost(”/api/orders”, async (CreateOrderRequest request, AppDbContext db) =>
{
if (string.IsNullOrWhiteSpace(request.Product))
return Results.BadRequest(”Product name is required.”);
if (request.Quantity <= 0)
return Results.BadRequest(”Quantity must be greater than 0.”);
var order = new Order
{
OrderId = Guid.NewGuid(),
Product = request.Product,
Quantity = request.Quantity
};
db.Orders.Add(order);
await db.SaveChangesAsync();
return Results.Created($”/api/orders/{order.OrderId}”, order);
});It worked, but you can see the problem.
Every time you reused CreateOrderRequest, you had to repeat the same validation logic.
Once your app grew, this got messy fast.
The new way in .NET 10
With .NET 10, validation is now built right in.
You don’t have to check anything manually.
All you do is register validation once at startup:
builder.Services.AddValidation();That single line enables automatic model validation for Minimal APIs.
The model
Now you can declare your validation rules directly on the model using attributes:
public record CreateOrderRequest(
[Required, MinLength(3)] string? Product,
[Required, Range(1, 100)] int Quantity
);Here’s what each attribute does:
[Required]makes sure the field isn’t missing.[MinLength(3)]ensures a product name has at least three characters.[Range(1, 100)]restricts the quantity to a valid range.
No extra logic. The framework does the validation automatically before your endpoint runs.
The simplified endpoint
With validation handled for you, the POST endpoint becomes clean and focused:
app.MapPost(”/api/orders”, async (CreateOrderRequest request, AppDbContext db) =>
{
var order = new Order
{
OrderId = Guid.NewGuid(),
Product = request.Product,
Quantity = request.Quantity
};
db.Orders.Add(order);
await db.SaveChangesAsync();
return Results.Created($”/api/orders/{order.OrderId}”, order);
});No manual checks. If validation fails, the request never even reaches this code.
How validation errors look
When a client sends invalid data, .NET automatically returns a structured JSON error response.
Example 1: Missing product
{
“quantity”: 2
}Response:
{
“title”: “One or more validation errors occurred.”,
“errors”: {
“Product”: [
“The Product field is required.”
]
}
}Example 2: Invalid quantity
{
“product”: “Cyberpunk 2077”,
“quantity”: 0
}Response:
{
“title”: “One or more validation errors occurred.”,
“errors”: {
“Quantity”: [
“The field Quantity must be between 1 and 100.”
]
}
}This response format is consistent and perfect for frontend frameworks like Blazor.
When you need to disable validation
Sometimes you might want to bypass validation for a specific endpoint, for example, when importing bulk data or testing edge cases.
You can disable it easily:
app.MapPost(”/api/orders”, CreateOrder)
.DisableValidation();That line tells .NET to skip validation for that route only.
Why this change matters
This update saves time and reduces bugs. Here’s why it’s a big deal:
Less repetition – no more
if(x == null)everywhere.Cleaner code – endpoints focus on logic, not checks.
Consistent errors – every endpoint uses the same response structure.
Single source of truth – validation lives with your model, not scattered across files.
It’s a small change that makes Minimal APIs feel much more complete.
Quick tip
If AddValidation() doesn’t show up, check your target framework:
<TargetFramework>net10.0</TargetFramework>Without .NET 10, you won’t see the new APIs yet.
Final thoughts
Minimal APIs have always been great for fast prototypes. But now, with built-in validation, they’re ready for serious production apps, too.
No boilerplate, no extra packages, just clean declarative rules that work out of the box.
P.S. Get the source code here. 🖥️



