ASP.NET Core 10 New Validation Features in Minimal APIs

ASP.NET Core 10 New Validation Features in Minimal APIs

ASP.NET Core 10 introduces built-in validation support for Minimal APIs. This is one of an important improvement because Minimal APIs can now validate incoming request data automatically before endpoint logic runs.

In the sample API, validation is enabled by using the following line:

builder.Services.AddValidation();

Once validation is enabled, ASP.NET Core can validate request body models, query string values, route values, and headers using familiar Data Annotations attributes such as [Required], [Range], [StringLength], [EmailAddress], and [RegularExpression].

What Are the New ASP.NET Core 10 Validation Features?

ASP.NET Core 10 adds automatic validation support for Minimal API endpoints. Earlier, automatic validation was commonly associated with MVC controllers and the [ApiController] attribute. Minimal APIs were lightweight and simple, but developers often had to write custom validation filters or manual validation logic.

With ASP.NET Core 10, Minimal APIs can now automatically validate:

  • Request body objects
  • Query string parameters
  • Route parameters
  • Header values
  • Nested complex objects
  • Collections
  • Record types and class types
  • Custom validation attributes
  • Model-level validation using IValidatableObject

For example, the sample API contains an order endpoint like this:

app.MapPost("/orders", (OrderRequest order) =>
{
    var response = new OrderResponse(
        Id: Guid.NewGuid(),
        CustomerName: order.CustomerName,
        ItemCount: order.Lines.Sum(line => line.Quantity),
        Total: order.TotalBeforeDiscount() * (1 - order.DiscountPercent / 100m));

    return TypedResults.Created($"/orders/{response.Id}", response);
});

The endpoint does not manually check whether the request is valid. ASP.NET Core performs validation before the endpoint handler executes.

The Following Figure Shows the Implementation fof the Validations.



Example of Model Validation

The OrderRequest model uses validation attributes directly on its properties:

public sealed record OrderRequest(
    [property: Required, StringLength(80, MinimumLength = 3)] string CustomerName,
    [property: Required, EmailAddress] string Email,
    [property: Required, MinLength(1)] List<OrderLine> Lines,
    [property: Required] Address ShippingAddress,
    [property: Range(0, 50)] decimal DiscountPercent) : IValidatableObject

If a client sends an invalid request, ASP.NET Core automatically returns a 400 Bad Request response with validation details.

Nested Object and Collection Validation

ASP.NET Core 10 validation can validate nested objects and collections. In this sample, OrderRequest contains a list of OrderLine objects and a nested Address object.

public sealed record OrderLine(
    [property: Required, StringLength(60, MinimumLength = 2)] string Sku,
    [property: Range(1, 25)] int Quantity,
    [property: Range(typeof(decimal), "0.01", "9999.99")] decimal UnitPrice);

public sealed record Address(
    [property: Required, StringLength(100)] string Street,
    [property: Required, StringLength(80)] string City,
    [property: Required, RegularExpression("^[A-Z]{2}$")] string CountryCode,
    [property: Required, StringLength(12, MinimumLength = 3)] string PostalCode);

This means invalid values inside child objects are detected automatically. For example, an empty SKU or invalid country code is reported as a validation error.

Model-Level Validation with IValidatableObject

ASP.NET Core 10 also supports complex validation logic through IValidatableObject. This is useful when validation depends on multiple properties.

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
    if (DiscountPercent > 0 && TotalBeforeDiscount() < 50)
    {
        yield return new ValidationResult(
            "Discounts require an order total of at least 50.00 before discount.",
            [nameof(DiscountPercent), nameof(Lines)]);
    }
}

In this example, a discount is allowed only when the order total is at least 50.00 before discount.

Custom Validation Attributes

ASP.NET Core 10 Minimal API validation also supports custom validation attributes. The sample API includes an EvenNumberAttribute:

public sealed class EvenNumberAttribute : ValidationAttribute
{
    public EvenNumberAttribute()
    {
        ErrorMessage = "The value must be an even number.";
    }

    public override bool IsValid(object? value)
    {
        return value is int number && number % 2 == 0;
    }
}

This custom validation attribute is used on a route parameter:

app.MapGet("/products/{productId:int}", ([EvenNumber] int productId) =>
{
    return TypedResults.Ok(new
    {
        ProductId = productId,
        Message = "The custom EvenNumberAttribute accepted this route value."
    });
});

If the user calls /products/3, validation fails because 3 is not an even number.

Why is This Feature Introduced in ASP.NET Core 10?

This feature was introduced to make Minimal APIs more powerful, consistent, and production-ready. Minimal APIs are designed to be simple and lightweight, but validation is a core requirement for real-world APIs.

Before ASP.NET Core 10, developers often needed to manually validate input in Minimal API endpoints or create custom endpoint filters. This added repeated code and made APIs harder to maintain.

ASP.NET Core 10 solves this by adding built-in validation support that works naturally with endpoint parameters and model types.

Advantages of ASP.NET Core 10 Validation

The biggest advantage is that validation becomes automatic. Endpoint code stays focused on business logic instead of validation plumbing.

Important Key advantages are as follows:

  • Cleaner Minimal API endpoint code
  • Less repeated validation logic
  • Automatic 400 Bad Request responses for invalid input
  • Consistent validation behavior across endpoints
  • Support for nested models and collections
  • Support for records and classes
  • Support for custom validation attributes
  • Better integration with OpenAPI and Swagger documentation
  • Improved maintainability for production APIs

What Is builder.Services.AddValidation()?

builder.Services.AddValidation() registers the ASP.NET Core validation services in the dependency injection container.

builder.Services.AddValidation();

After this service is registered, ASP.NET Core can automatically discover validation metadata from Minimal API endpoint parameters and model types.

It enables validation attributes such as:

  • [Required]
  • [StringLength]
  • [Range]
  • [EmailAddress]
  • [RegularExpression]
  • Custom attributes derived from ValidationAttribute

In short, AddValidation() turns on the new ASP.NET Core 10 validation pipeline for Minimal APIs.

Validation Opt-Out with DisableValidation()

ASP.NET Core 10 also allows validation to be disabled for specific endpoints by using DisableValidation().

app.MapPost("/orders/draft", (OrderRequest order) =>
{
    return TypedResults.Accepted($"/orders/draft/{Guid.NewGuid()}", new
    {
        Message = "Validation was intentionally disabled for this draft endpoint.",
        order.CustomerName,
        Lines = order.Lines.Count
    });
})
.DisableValidation();

This is useful for draft, import, or partial-save endpoints where incomplete data may be acceptable.

What Is builder.Services.AddProblemDetails()?

builder.Services.AddProblemDetails() registers support for standardized error responses using the Problem Details format.

builder.Services.AddProblemDetails(options =>
{
    options.CustomizeProblemDetails = context =>
    {
        context.ProblemDetails.Extensions["traceId"] = context.HttpContext.TraceIdentifier;
        context.ProblemDetails.Extensions["api"] = "AspNetCore10ValidationApi";
    };
});

Problem Details is a standard JSON format for representing API errors. It commonly includes fields such as type, title, status, and validation error details.

What are the Advantage of AddProblemDetails()?

The main advantage of AddProblemDetails() is consistency. Instead of every endpoint returning a different error format, the API can return predictable, machine-readable error responses.

This helps frontend applications, mobile apps, and API clients handle errors more easily.

For example, a validation error response can look like this:

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "Email": [
      "The Email field is not a valid e-mail address."
    ]
  },
  "traceId": "0HNL...",
  "api": "AspNetCore10ValidationApi"
}

The added traceId is useful for troubleshooting because it can be correlated with server logs. The added api value identifies which API produced the error.

Conclusion

ASP.NET Core 10 validation support is a major improvement for Minimal APIs. It brings automatic validation, cleaner endpoint code, better consistency, nested object validation, custom validation support, and standardized error handling.

builder.Services.AddValidation() enables the validation pipeline, while builder.Services.AddProblemDetails() improves the structure and consistency of error responses.  Together, these features make ASP.NET Core 10 Minimal APIs easier to build, easier to maintain, and better suited for real-world production applications.

Code for this article can be downloaded from this link.

Popular posts from this blog

ASP.NET Core 8: Creating Custom Authentication Handler for Authenticating Users for the Minimal APIs

ASP.NET Core 7: Using PostgreSQL to store Identity Information

Azure AI Document Intelligence: Processing an Invoice and Saving it in Azure SQL Server Database using Azure Functions