Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

FluentValidation ใน C# คืออะไร และวิธีใช้งานพื้นฐาน

FluentValidation เป็น .NET Library สำหรับสร้าง Validation Rules แบบ Strongly-typed Fluent Interface ใช้ Lambda Expressions ทำให้โค้ดอ่านง่าย รวม Validation Logic ไว้ที่เดียว (Separation of Concerns)

ทำไมต้องใช้ FluentValidation?

  • แยก Validation Logic ออกจาก Domain Model (Clean Architecture)
  • Fluent API: Chainable, Readable, Discoverable (IntelliSense)
  • รองรับ Async, Conditional, Collection, Nested Validation
  • Integrate กับ ASP.NET Core, MVC, WebAPI, Blazor, Minimal APIs ได้ง่าย
  • Testing ง่าย (Validator เป็น Class ธรรมดา)

ติดตั้ง

dotnet add package FluentValidation
dotnet add package FluentValidation.AspNetCore // สำหรับ ASP.NET Core Integration
// หรือ
<PackageReference Include="FluentValidation" Version="11.9.0" />

ตัวอย่างพื้นฐาน

using FluentValidation;
using FluentValidation.Results;
using System;

public class PersonModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public decimal AccountBalance { get; set; }
    public DateTime DateOfBirth { get; set; }
}

public class PersonValidator : AbstractValidator<PersonModel>
{
    public PersonValidator()
    {
        RuleFor(p => p.FirstName)
            .Cascade(CascadeMode.StopOnFirstFailure) // หยุดที่ Error แรก
            .NotEmpty().WithMessage("{PropertyName} ห้ามว่าง")
            .Length(2, 50).WithMessage("{PropertyName} ความยาวต้อง 2-50 ตัวอักษร (ปัจจุบัน: {TotalLength})")
            .Must(BeValidName).WithMessage("{PropertyName} ต้องเป็นตัวอักษรเท่านั้น");
            
        RuleFor(p => p.LastName)
            .Cascade(CascadeMode.StopOnFirstFailure)
            .NotEmpty().WithMessage("{PropertyName} ห้ามว่าง")
            .Length(2, 50).WithMessage("{PropertyName} ความยาวต้อง 2-50 ตัวอักษร");
            
        RuleFor(p => p.AccountBalance)
            .GreaterThan(0).WithMessage("{PropertyName} ต้องมากกว่า 0");
            
        RuleFor(p => p.DateOfBirth)
            .LessThanOrEqualTo(DateTime.Today).WithMessage("{PropertyName} ต้องไม่เป็นอนาคต");
    }
    
    private bool BeValidName(string name)
    {
        if (string.IsNullOrWhiteSpace(name)) return false;
        var cleaned = name.Replace(" ", "").Replace("-", "");
        return cleaned.All(char.IsLetter);
    }
}

static void Main()
{
    var person = new PersonModel
    {
        FirstName = "",           // Empty - Fail
        LastName = "S",           // Length 1 - Fail
        AccountBalance = 100,
        DateOfBirth = DateTime.Today
    };
    
    var validator = new PersonValidator();
    ValidationResult result = validator.Validate(person);
    
    if (!result.IsValid)
    {
        foreach (var error in result.Errors)
        {
            Console.WriteLine($"[{error.PropertyName}] {error.ErrorMessage}");
        }
    }
    else
    {
        Console.WriteLine("Valid!");
    }
}

ผลลัพธ์

[FirstName] FirstName ห้ามว่าง
[LastName] LastName ความยาวต้อง 2-50 ตัวอักษร (ปัจจุบัน: 1)

Placeholders ใน Error Message

Placeholder ค่า
{PropertyName} ชื่อ Property (เช่น FirstName)
{PropertyValue} ค่าที่ Validate
{TotalLength} ความยาว String/Collection
{MinLength}, {MaxLength} ค่าที่ตั้งใน Length/Min/Max
{ComparisonValue} ค่าเปรียบเทียบ (GreaterThan, LessThan)

Integration กับ ASP.NET Core

// Program.cs (.NET 6+)
builder.Services.AddControllers()
    .AddFluentValidationAutoValidation() // Auto Validate + ModelState
    .AddFluentValidationClientsideAdapters(); // Client-side (optional)

builder.Services.AddValidatorsFromAssemblyContaining<Program>(); // Scan Validators

สรุป

FluentValidation = Validation Library ที่ทรงพลัง อ่านง่าย ทดสอบง่าย รองรับ Scenario ซับซ้อน เหมาะสำหรับ Enterprise Applications