API clients need predictable responses when requests contain invalid data. If each endpoint reports validation errors differently, client applications must implement special handling for every operation.
ASP.NET Core provides mechanisms for validating request models and returning standardized error responses. A consistent validation strategy improves usability, debugging, and API maintainability.
Use Request Models
A request model defines the fields an endpoint expects and the validation rules those fields must satisfy.
using System.ComponentModel.DataAnnotations;
public sealed class CreateUserRequest
{
[Required]
[StringLength(100, MinimumLength = 2)]
public string Name { get; init; } = "";
[Required]
[EmailAddress]
public string Email { get; init; } = "";
}
This model specifies basic requirements for a user’s name and email address. More complex business rules may require additional validation logic.
Let ASP.NET Core Handle Model Validation
Controller-based APIs using [ApiController] can automatically return a validation response when model binding or validation fails.
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/users")]
public class UsersController : ControllerBase
{
[HttpPost]
public IActionResult Create(CreateUserRequest request)
{
// Perform the application operation.
return Created("/api/users/123", new
{
id = 123,
request.Name,
request.Email
});
}
}
The example demonstrates the endpoint structure, not a complete persistence implementation. In a real application, the identifier should come from the created resource.
Use a Consistent Error Format
ASP.NET Core supports Problem Details responses for communicating HTTP errors in a standard structure. A validation response can include a title, status code, and field-level error details.
Clients should rely on documented fields rather than parsing human-readable message strings to determine what went wrong.
Keep error messages useful without exposing internal exception details, database information, or sensitive values submitted by users.
Distinguish Validation from Business Conflicts
Not every rejected request is a field-validation error.
Examples include:
- A missing required field.
- An invalid email format.
- An email address that already belongs to another account.
- A request that conflicts with the current resource state.
- A user who lacks permission to perform an operation.
Represent these cases according to the API’s documented semantics. Consistent HTTP status codes and response bodies make client behavior easier to implement.
Validate at the Appropriate Boundaries
Data annotations work well for many straightforward rules. Complex validation may require a dedicated validator or application service.
Business invariants should also be enforced where the operation is performed, particularly when concurrent requests could bypass a simple preliminary check.
For example, checking whether an email is already used is not a substitute for a database uniqueness constraint when two requests can arrive simultaneously.
Test the Error Contract
Write integration tests for malformed input, missing fields, invalid values, and business conflicts. Verify the response status and structure, not merely that the endpoint rejects the request.
Conclusion
Consistent API validation responses reduce client complexity and make failures easier to diagnose. Use request models, standard error formats, clear HTTP semantics, and appropriate business-rule enforcement to create predictable ASP.NET Core APIs.