How to Use Fluent Validation in ASP.NET Core

What is FluentValidation?
FluentValidation is a validation library for .NET Used for building strongly type validation rules for your business objects.

  • Creating ASP.NET Core Application
  • Installing FluentValidation package for ASP.NET Core

Creating ASP.NET Core Application
We are going to create ASP.NET Core Web Application for that we are going to choose ‘ASP.NET Core Web Application‘ template.

Next, we are going to set Project Name ‘WebApplication14‘ and location and in last part, we are going to choose .Net Core framework and ASP.NET Core Version 3.0 as framework for application and few advance settings for such as configuring https and enabling docker we are not going to enable both of settings for this project.

Now finally click on create button to create a project.
Project structure
The project structure generated according to the configuration.

After creating a project, next, we are first going to install ‘FluentValidation.AspNetCore‘ package from NuGet package.

Installing FluentValidation
Installing ‘FluentValidation.AspNetCore’ package from NuGet package.

After installing the package next, we are going configure FluentValidation.AspNetCore package in Startup class.

Configuring FluentValidation.AspNetCore package in Startup class

We are going to Registering FluentValidation Service inside ConfigureServices method as shown below.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews().AddFluentValidation();
}

After Registering service next, we are going to add employee class for adding validation.

Adding Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebApplication14.Models
{
    public class Employee
    {
        public string Name { get; set; }
        public int Id { get; set; }
        public string Address { get; set; }
        public string Email { get; set; }
        public string Age { get; set; }
        public decimal Salary { get; set; }
    }
}

After adding a model next, we are going to add another class for writing validation for Employee class.

Built-in Validators

  • NotNull (‘.NotNull’):- to check the property is null.
  • NotEmpty (‘.NotEmpty’):- to check the property is null, empty or has whitespace.
  • NotEqual (‘.NotEqual’):- to check the specified property is not equal to a particular value.
  • Equal Validator (‘.Equal’):- to check the value of the specified property is equal to a particular value.
  • Length Validator (‘.Length’):- to check the length of a particular string property is within the specified range.
  • MaxLength Validator (‘.MaximumLength’):- to check the length of a particular string property is no longer than the specified value.
  • MinLength Validator (‘.MinimumLength’):- to check the length of a particular string property is longer than the specified value.
  • Less Than Validator (‘.LessThan’):- to check the length of the specified property is less than a particular value
  • LessThanOrEqual Validator (‘.LessThanOrEqualTo’): to check the value of the specified property is less than or equal to a particular value.
  • Greater Than Validator (‘.GreaterThan’):- to check the value of the specified property is greater than a particular value.
  • Regular Expression Validator (‘.Matches’):- to check the value of the specified property matches the given regular expression.
  • Email Validator Validator (‘.EmailAddress’) :- to check the value of the specified property is a valid email address.

Reference the – https://fluentvalidation.net/built-in-validators

Adding EmployeeValidator class for Creating Validator

After adding EmployeeValidator class next, we are going to inherit it with AbstractValidator class which is a generic abstract class there we are going to pass our model name ‘Employee‘.
Then in the constructor of that class, we are going to write validations.

using FluentValidation;
namespace WebApplication14.Models
{
    public class EmployeeValidator : AbstractValidator<Employee>
    {
        public EmployeeValidator()
        {
            RuleFor(x => x.Id).NotNull();
            RuleFor(reg => reg.Name).NotEmpty().MinimumLength(8).MaximumLength(50);
            RuleFor(x => x.Address).NotNull().MaximumLength(100);
            RuleFor(x => x.Email).EmailAddress();
            RuleFor(x => x.Age).InclusiveBetween(18, 60);
            RuleFor(x => x.Salary).NotNull();
        }
   }
}
  1. The rule for checking the id is not null.
    RuleFor(x => x.Id).NotNull();
  2. The rule for checking Name is not null and it must be minimum of 8 characters and maximum 50 characters.
    RuleFor(reg => reg.Name).NotEmpty().MinimumLength(8).MaximumLength(50);
  3. The rule for checking Address is not null and allowing Maximum 100 characters.
    RuleFor(x => x.Address).NotNull().MaximumLength(100);
  4. Rule for checking Email Address
    RuleFor(x => x.Email).EmailAddress();
  5. The rule for checking Age between 18 to 60
    RuleFor(x => x.Age).InclusiveBetween(18, 60);
  6. The rule for checking Salary is not null
    RuleFor(x => x.Salary).NotNull();

After writing validation rules next, we are going register EmployeeValidator class in ConfigureServices method in startup class.

For registering Validator, there are three ways.

  1. Registering each validator in Service with AddTransient.
  2. Registering using ‘RegisterValidatorsFromAssemblyContaining‘ method registers all validators derived from AbstractValidator class within the assembly containing the specified type.
  3. Registering using ‘RegisterValidatorsFromAssembly‘ method.

1. Registering each validator in Service with AddTransient

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews().AddFluentValidation();
    // First way
    services.AddTransient<IValidator<Employee>, EmployeeValidator>();
}

2. Registering Using ‘RegisterValidatorsFromAssemblyContaining’ Method

public void ConfigureServices(IServiceCollection services)
 {
     // Second way
     services.AddControllersWithViews().AddFluentValidation(fv =>
     {
         fv.RegisterValidatorsFromAssemblyContaining<EmployeeValidator>();
     });
 }

3. Registering Using ‘RegisterValidatorsFromAssembly’ Method

public void ConfigureServices(IServiceCollection services)
{
    // Third way
    services.AddControllersWithViews().AddFluentValidation(fv =>
    {
        fv.RegisterValidatorsFromAssembly(Assembly.GetExecutingAssembly());
    });
}

Adding a Controller with 2 Action Method to Perform validation

For performing validation and display error method on the view, we need to add a controller and 2 action method one for handling get and another for handling post request along with Views.

using Microsoft.AspNetCore.Mvc;
using WebApplication14.Models;

namespace WebApplication14.Controllers
{
    public class DefaultController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public IActionResult Index(Employee Employee)
        {
            if (!ModelState.IsValid)
            {
                return View(Employee);
            }
            return View(Employee);
        }
    }
}

Index View

@model Employee

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<h4>Employee</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Index">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Name" class="control-label"></label>
                <input asp-for="Name" class="form-control" />
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Id" class="control-label"></label>
                <input asp-for="Id" class="form-control" />
                <span asp-validation-for="Id" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Address" class="control-label"></label>
                <input asp-for="Address" class="form-control" />
                <span asp-validation-for="Address" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Email" class="control-label"></label>
                <input asp-for="Email" class="form-control" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Age" class="control-label"></label>
                <input asp-for="Age" class="form-control" />
                <span asp-validation-for="Age" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Salary" class="control-label"></label>
                <input asp-for="Salary" class="form-control" />
                <span asp-validation-for="Salary" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

Next, we are going to run the application and test it to see FluentValidation is working properly.

Now if you see, Validation is working the, but error messages are not easy to read. Let’s see how to write a custom error message next.

Adding Custom Error Messages

For adding a custom message with FluentValidation, we need to use WithMessage method as shown below.

using FluentValidation;

namespace WebApplication14.Models
{
    public class EmployeeValidator : AbstractValidator<Employee>
    {
        public EmployeeValidator()
        {
            RuleFor(x => x.Id).NotNull()
                .WithMessage("Please Enter 'Id'");

            RuleFor(reg => reg.Name).NotEmpty()
                .WithMessage("Please Enter 'Name'")
                .MinimumLength(8).WithMessage("minimum length of 8 characters are allowed")
                .MaximumLength(50).WithMessage("maximum length of 50 charaters is allowed");

            RuleFor(x => x.Address).NotNull()
                .WithMessage("Please Enter 'Address'")
                .MaximumLength(100).WithMessage("maximum length of 100 charaters is allowed");

            RuleFor(x => x.Email)
                .EmailAddress();

            RuleFor(x => x.Age).NotNull()
                .WithMessage("Please Enter 'Age'")
                .InclusiveBetween(18, 60)
                .WithMessage("'Age' must be between 18 to 60"); ;

            RuleFor(x => x.Salary)
                .NotNull().WithMessage("Please Enter 'Salary'"); ;
        }
    }
}

Now, after writing the custom error message next again, we are going to run the application to View Custom Error messages.

In this part, we have learned how to use Fluentvalidation in ASP.NET Core 3.0 in a step by step way.

By Saineshwar Bageri

I am Microsoft MVP | C# Corner MVP | Code Project MVP | FULL STACK .NET Developer and working on .Net Web Technology (Asp.net, Asp.net Core,.Net Core, C#, Sqlserver, MVC, Windows, Console Application, javascript, jquery, json, ORM Dapper) and also a freelance developer.