Isaac.

Validation in ASP.NET Core

Learn how to validate user input effectively using ASP.NET Core's built-in and third-party validation tools.

By EMEPublished: February 20, 2025
aspnetvalidationdata validationfluent validationmodel binding

A Simple Analogy

Imagine a nightclub with a bouncer at the door. The bouncer checks IDs, makes sure people meet age requirements, and turns away anyone who doesn't qualify. In ASP.NET Core, validation is that bouncer—it checks incoming data before it enters your application. Bad data never makes it past the bouncer; only clean, safe data gets in.


What Is Validation?

Validation is the process of checking that incoming data (from users, APIs, forms) meets your requirements before you use it. It ensures data is correct, safe, and meaningful.


Why Use Validation?

  • Data integrity: Ensure data is correct and consistent
  • Security: Prevent injection attacks and malicious input
  • User experience: Show clear error messages so users know how to fix mistakes
  • Business logic: Enforce rules (email format, age requirements, password strength)
  • Database protection: Avoid storing garbage or invalid data

Built-in Data Annotations

ASP.NET Core provides simple validation attributes:

public class User
{
    [Required(ErrorMessage = "Name is required")]
    [StringLength(100)]
    public string Name { get; set; }

    [EmailAddress(ErrorMessage = "Invalid email")]
    public string Email { get; set; }

    [Range(18, 120, ErrorMessage = "Age must be 18-120")]
    public int Age { get; set; }

    [RegularExpression(@"^\d{3}-\d{3}-\d{4}$")]
    public string PhoneNumber { get; set; }
}

Common Validation Attributes

  • [Required] — Field is mandatory
  • [StringLength(max)] — Maximum character length
  • [Range(min, max)] — Numeric range
  • [EmailAddress] — Valid email format
  • [Url] — Valid URL
  • [RegularExpression(pattern)] — Matches regex pattern
  • [Compare] — Two fields match (password confirmation)
  • [CreditCard] — Valid credit card number

Model Binding & Automatic Validation

ASP.NET Core automatically validates when model binding occurs:

[HttpPost("/users")]
public IActionResult CreateUser(User user)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState); // Returns 400 with errors
    }
    // Process valid user
}

FluentValidation (Advanced)

For complex rules, use FluentValidation:

dotnet add package FluentValidation.AspNetCore
public class UserValidator : AbstractValidator<User>
{
    public UserValidator()
    {
        RuleFor(u => u.Email)
            .NotEmpty()
            .EmailAddress()
            .MustAsync(async (email, ct) => !await EmailExistsAsync(email));

        RuleFor(u => u.Password)
            .NotEmpty()
            .MinimumLength(8)
            .Matches("[A-Z]").WithMessage("Must contain uppercase")
            .Matches("[0-9]").WithMessage("Must contain digit");

        RuleFor(u => u.Age)
            .InclusiveBetween(18, 120)
            .When(u => u.Age.HasValue);
    }
}

Register in Program.cs:

builder.Services.AddFluentValidationAutoValidation();
builder.Services.AddValidatorsFromAssemblyContaining<UserValidator>();

Custom Validation Logic

Create custom validators for business rules:

public class ValidateFutureDate : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        if (value is DateTime date && date > DateTime.Now)
            return ValidationResult.Success;

        return new ValidationResult("Date must be in the future");
    }
}

public class Meeting
{
    [ValidateFutureDate]
    public DateTime ScheduledDate { get; set; }
}

Server-Side vs. Client-Side Validation

  • Server-side: Always required (users can bypass client-side)
  • Client-side: JavaScript validation for quick feedback (better UX)

ASP.NET Core supports both. Attributes work on server; Blazor and jQuery validate client-side automatically.


Practical Examples

  • Registration form: Validate username (unique), email (format), password (strength)
  • E-commerce: Validate product quantity, price, shipping address
  • API: Validate incoming JSON, reject malformed requests
  • File upload: Check file size, extension, MIME type
  • Search: Validate date ranges, sort options, pagination

Real-World Use Cases

  • User registration: Email uniqueness, password complexity
  • Payment processing: Valid credit card, address verification
  • Appointment booking: Dates in future, no double-booking
  • Account updates: Email not already used, phone format valid
  • API integration: Required fields, data type correctness

Best Practices

  • Validate on both server and client
  • Always validate on the server (never trust the client)
  • Provide clear, helpful error messages
  • Use built-in attributes for simple rules
  • Use FluentValidation for complex business logic
  • Validate early, fail fast
  • Log validation failures for debugging
  • Test your validators

Related Concepts to Explore

  • Data annotation attributes
  • Model binding in ASP.NET Core
  • Custom model binders
  • Blazor form validation
  • Input sanitization
  • CSRF protection
  • XSS prevention
  • API versioning and contract validation
  • OpenAPI schema validation
  • Error handling and exception filters

Summary

Validation is your app's first line of defense against bad data. Whether you use simple data annotations or complex FluentValidation rules, validation ensures your application stays secure, reliable, and user-friendly. Always validate—on both the client for UX and on the server for security.