Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

FluentValidation trong C#: Tổng quan và cách sử dụng

FluentValidation là thư viện validation phổ biến cho .NET, cho phép định nghĩa quy tắc validation tách biệt khỏi model (POCO), sử dụng fluent API dễ đọc, dễ bảo trì.

Tại sao dùng FluentValidation?

  • Separation of Concerns: Validation logic tách khỏi domain model.
  • Fluent API: Dễ đọc, chainable, IntelliSense tốt.
  • Testable: Validator là class riêng, dễ unit test.
  • Rich built-in validators: NotNull, Email, Length, Regex, InclusiveBetween, CreditCard...
  • Custom validators: Must, Custom, CustomAsync.
  • Integration: ASP.NET Core, Blazor, WPF, MAUI, MediatR, Minimal APIs.

Cài đặt

dotnet add package FluentValidation
dotnet add package FluentValidation.AspNetCore // Cho ASP.NET Core integration

Ví dụ cơ bản

using FluentValidation;
using System;

public class User
{
    public string Username { get; set; }
    public string Email { get; set; }
    public int Age { get; set; }
    public string Password { get; set; }
}

public class UserValidator : AbstractValidator<User>
{
    public UserValidator()
    {
        RuleFor(u => u.Username)
            .NotEmpty().WithMessage("Username is required")
            .Length(3, 20).WithMessage("Username must be 3-20 chars")
            .Matches("^[a-zA-Z0-9_]+$").WithMessage("Username only alphanumeric/underscore");

        RuleFor(u => u.Email)
            .NotEmpty().WithMessage("Email is required")
            .EmailAddress().WithMessage("Invalid email format");

        RuleFor(u => u.Age)
            .InclusiveBetween(18, 100).WithMessage("Age must be 18-100");

        RuleFor(u => u.Password)
            .NotEmpty().WithMessage("Password required")
            .MinimumLength(8).WithMessage("Password min 8 chars")
            .Matches("[A-Z]").WithMessage("Password needs uppercase")
            .Matches("[0-9]").WithMessage("Password needs digit");
    }
}

Chạy validation

var user = new User { Username = "ab", Email = "invalid", Age = 15, Password = "weak" };
var validator = new UserValidator();
ValidationResult result = validator.Validate(user);

if (!result.IsValid)
{
    foreach (var error in result.Errors)
        Console.WriteLine($"{error.PropertyName}: {error.ErrorMessage}");
}

Kết quả

Username: Username must be 3-20 chars
Email: Invalid email format
Age: Age must be 18-100
Password: Password min 8 chars
Password: Password needs uppercase
Password: Password needs digit

ASP.NET Core Integration

// Program.cs
builder.Services.AddControllers()
    .AddFluentValidationAutoValidation()
    .AddFluentValidationClientsideAdapters();

builder.Services.AddValidatorsFromAssemblyContaining<Program>(); // Auto register

// Controller - tự động validate, trả 400 nếu invalid
[ApiController]
[Route("api/users")]
public class UsersController : ControllerBase
{
    [HttpPost]
    public IActionResult Create(User user) => Ok(user); // ModelState tự validate
}

Advanced Features

  • Conditional Validation: .When(u => u.IsActive, () => RuleFor(...))
  • Async Validation: .MustAsync(async (x, ct) => await CheckUnique(x))
  • Cross-property: RuleFor(u => u.ConfirmPassword).Equal(u => u.Password)
  • Collections: RuleForEach(u => u.Addresses).SetValidator(new AddressValidator())
  • Localization: WithMessage(() => Localizer["Key"])

Best Practice: Một validator per model, đặt cùng folder với model hoặc folder Validators/. Test validator độc lập.