Introduction
Validation is one of the most important parts of building production-ready web applications. Without proper validation, users may submit incomplete, incorrect, or malicious data, which may lead to database corruption, logic failures, inconsistent business workflows, and security vulnerabilities.
ASP.NET Core provides a built-in model validation framework that works seamlessly with controllers, minimal APIs, and Razor pages. It is based on attributes, reusable rules, and optional custom logic for complex real-world scenarios. Validation ensures that the backend does not trust frontend data blindly, even if Angular, React, or Blazor already perform client-side checks.
This article examines how model validation works in real-life enterprise development with step-by-step implementation, examples, and best practices.
Real-World Problem Statement
A logistics company built a freight booking web app. Their front-end UI allowed users to enter shipment weight, dimensions, pick-up date, and customer details. Initially, validation happened only in Angular, assuming backend protection was unnecessary.
Within three months:
Incorrect data formats reached the database.
Some required fields were missing because users bypassed validation using developer tools.
Negative weight values caused pricing miscalculations.
Fake customer emails made automated notifications fail.
After an internal audit, the engineering team implemented server-side validation using ASP.NET Core Model Validation.
How Model Validation Works in ASP.NET Core
When a request is received, ASP.NET Core automatically attempts to bind request data to the model.
Validation attributes defined on properties are checked.
If validation fails, the request is immediately blocked.
An appropriate error response is returned (usually 400 Bad Request).
The controller method does not execute until the data is valid.
This approach ensures backend consistency even if client-side validation is bypassed.
Basic Example Model with Required and Range Validation
public class BookingRequest
{
[Required(ErrorMessage = "Customer Name is required.")]
public string CustomerName { get; set; }
[Required]
[EmailAddress(ErrorMessage = "Invalid email format.")]
public string Email { get; set; }
[Range(1, 10000, ErrorMessage = "Weight must be between 1 and 10000 kg.")]
public decimal Weight { get; set; }
[Required]
public DateTime PickupDate { get; set; }
}
Controller Example
[ApiController]
[Route("api/[controller]")]
public class BookingController : ControllerBase
{
[HttpPost("create")]
public IActionResult CreateBooking([FromBody] BookingRequest request)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok("Booking Created Successfully");
}
}
Workflow Diagram
User Input
|
V
Model Binding
|
V
Validate Attributes (Required, Range, Custom)
|
+--> Failure --> Return 400 with validation errors
|
V
Success
|
V
Controller Executes Business LogicFlowchart
┌─────────────────────┐
│ Receive API Request │
└───────┬────────────┘
│
▼
┌──────────────────────────┐
│ Bind Values to Model │
└───────┬──────────────────┘
│
▼
┌───────────────────────┐
│ Perform Validation │
└─────────┬─────────────┘
│
┌─────────▼──────────────┐
│ Valid? │
└───────┬───────┬────────┘
│ │
YES NO
│ │
▼ ▼
┌───────────────────┐ ┌────────────────────┐
│ Execute Controller │ │ Return 400 Error │
│ Logic │ │ with Errors │
└───────────────────┘ └────────────────────┘

Join the conversation! Your thoughts help the community grow.