Users Pricing

blog

home / developersection / blogs / implement fluent validation in asp.net core api
Implement Fluent Validation in ASP.NET Core API

Implement Fluent Validation in ASP.NET Core API

Ravi Vishwakarma 30 15 May 2026 Updated 15 May 2026

Validation is one of the most important parts of API development. Without proper validation, applications may store invalid, incomplete, or harmful data in the database.

Although ASP.NET Core provides built-in model validation using Data Annotations, many developers prefer FluentValidation because it offers:

  • cleaner validation logic
  • better readability
  • reusable rules
  • advanced validation support

What is FluentValidation?

FluentValidation is a popular .NET library for building strongly-typed validation rules using a fluent interface.

Instead of decorating models with attributes like:

[Required]
[StringLength(50)]

FluentValidation allows writing validation rules in separate classes.

Why Use FluentValidation?

Advantages

  • Clean separation of concerns
  • Easy to maintain
  • Better readability
  • Reusable validation logic
  • Supports complex validations
  • Custom error messages
  • Conditional validation
  • Async validation support

Create ASP.NET Core Web API

Create a new project:

dotnet new webapi -n FluentValidationDemo

Move into project:

cd FluentValidationDemo

Install FluentValidation Package

Install the NuGet package:

dotnet add package FluentValidation.AspNetCore

Create Model Class

Example model:

public class Product
{
    public string Name { get; set; }

    public decimal Price { get; set; }

    public int Stock { get; set; }

    public string Email { get; set; }
}

Create Validator Class

Create a folder named:

Validators

Now create:

ProductValidator.cs

Example:

using FluentValidation;

public class ProductValidator : AbstractValidator<Product>
{
    public ProductValidator()
    {
        RuleFor(x => x.Name)
            .NotEmpty()
            .WithMessage("Product name is required")
            .MaximumLength(50);

        RuleFor(x => x.Price)
            .GreaterThan(0)
            .WithMessage("Price must be greater than zero");

        RuleFor(x => x.Stock)
            .GreaterThanOrEqualTo(0);

        RuleFor(x => x.Email)
            .EmailAddress()
            .WithMessage("Invalid email format");
    }
}

Register FluentValidation

In .NET 6/7/8 using Program.cs:

builder.Services.AddControllers();

builder.Services.AddFluentValidationAutoValidation();

builder.Services.AddValidatorsFromAssemblyContaining<ProductValidator>();

Add namespace:

using FluentValidation;
using FluentValidation.AspNetCore;

Create API Controller

Example controller:

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    [HttpPost]
    public IActionResult Create(Product product)
    {
        return Ok(new
        {
            Message = "Product created successfully",
            Data = product
        });
    }
}

Test Validation

Valid Request

{
  "name": "Laptop",
  "price": 50000,
  "stock": 10,
  "email": "admin@test.com"
}

Invalid Request

{
  "name": "",
  "price": -10,
  "stock": -5,
  "email": "wrong-email"
}

Validation Response

ASP.NET Core automatically returns:

{
  "errors": {
    "Name": [
      "Product name is required"
    ],
    "Price": [
      "Price must be greater than zero"
    ],
    "Stock": [
      "'Stock' must be greater than or equal to '0'."
    ],
    "Email": [
      "Invalid email format"
    ]
  }
}

Common FluentValidation Rules

Rule Purpose
NotEmpty() Required field
NotNull() Prevent null
Length() String length
MaximumLength() Max characters
MinimumLength() Min characters
EmailAddress() Validate email
GreaterThan() Numeric validation
Equal() Match value
Must() Custom validation

Conditional Validation

Example:

RuleFor(x => x.Stock)
    .GreaterThan(0)
    .When(x => x.Price > 1000);

This validates stock only if price exceeds 1000.

Custom Validation

Example:

RuleFor(x => x.Name)
    .Must(name => name.StartsWith("P"))
    .WithMessage("Name must start with P");

Async Validation

Useful for database checks.

Example:

RuleFor(x => x.Email)
    .MustAsync(async (email, cancellation) =>
    {
        return await IsEmailUnique(email);
    });

Nested Object Validation

FluentValidation supports complex models.

Example:

RuleFor(x => x.Address)
    .SetValidator(new AddressValidator());

Benefits Over Data Annotations

Data Annotations FluentValidation
Validation inside model Separate validation class
Limited flexibility Highly flexible
Harder to test Easy unit testing
Less readable Cleaner syntax

Best Practices

Keep Validators Separate

Store validators inside dedicated folders.

Use Meaningful Messages

Bad:

Invalid input

Good:

Price must be greater than zero

Reuse Validators

Avoid duplicate validation logic.

Use Async Validation Carefully

Database checks can affect performance.

Real-World Example

Suppose an e-commerce API receives:

  • product creation requests
  • order data
  • customer registration
  • Without validation:
  • negative prices
  • invalid emails
  • empty names

may enter the database.

Using FluentValidation ensures:

  • cleaner API responses
  • secure input handling
  • reliable business rules

Conclusion

FluentValidation is a powerful and clean way to implement validation in ASP.NET Core APIs. It improves maintainability, readability, and flexibility compared to traditional Data Annotations.

By using FluentValidation, developers can:

  • centralize validation logic
  • create reusable rules
  • build cleaner APIs
  • improve application reliability

For modern ASP.NET Core applications, FluentValidation has become one of the most preferred validation libraries in enterprise development.


Ravi Vishwakarma

IT-Hardware & Networking

Ravi Vishwakarma is a dedicated Software Developer with a passion for crafting efficient and innovative solutions. With a keen eye for detail and years of experience, he excels in developing robust software systems that meet client needs. His expertise spans across multiple programming languages and technologies, making him a valuable asset in any software development project.