C# İle Fluentvalidation Kullanarak Veri Doğrulama Katmanı Nasıl Yapılır?

C# İle Fluentvalidation Kullanarak Veri Doğrulama Katmanı Nasıl Yapılır?
C# İle Fluentvalidation Kullanarak Veri Doğrulama Katmanı Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

FluentValidation kütüphanesini projenize dahil etmek için .NET 8.0 veya üzeri bir sürüm kullanmanız önerilir. Projenizin kök dizininde terminali açarak veya NuGet Paket Yöneticisi üzerinden gerekli paketi yüklemelisiniz. Bu kütüphane, iş mantığınızı (business logic) veri doğrulama kurallarından ayırmanıza yardımcı olur.

Kurulum için aşağıdaki komutu kullanabilirsiniz:

dotnet add package FluentValidation.DependencyInjectionExtensions

Bu paket, FluentValidation'ın .NET'in yerleşik bağımlılık enjeksiyonu (Dependency Injection) mekanizmasıyla sorunsuz çalışmasını sağlar. Kurulum tamamlandıktan sonra, projenizde doğrulama katmanını oluşturmaya başlayabilirsiniz.

Adım Adım FluentValidation Sınıfı Oluşturma

Doğrulama kurallarını tanımlarken, her model sınıfı için ayrı bir "Validator" sınıfı oluşturmak en iyi pratiktir. Örneğin, bir kullanıcı kayıt işlemi için UserRegisterRequest sınıfımız olduğunu varsayalım. Bu sınıfın kurallarını AbstractValidator sınıfından türeterek tanımlarız.

Aşağıdaki örnekte, bir kullanıcı kaydı için temel doğrulama kurallarının nasıl yazılacağını görebilirsiniz:

using FluentValidation;

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

public class UserRegisterValidator : AbstractValidator
{
    public UserRegisterValidator()
    {
        RuleFor(x => x.Username).NotEmpty().WithMessage("Kullanıcı adı boş bırakılamaz.");
        RuleFor(x => x.Email).EmailAddress().WithMessage("Geçerli bir e-posta adresi giriniz.");
        RuleFor(x => x.Age).InclusiveBetween(18, 99).WithMessage("Yaşınız 18 ile 99 arasında olmalıdır.");
    }
}

Burada RuleFor metodu, doğrulanacak özelliği belirtir. NotEmpty, EmailAddress ve InclusiveBetween ise hazır doğrulama metotlarıdır. WithMessage ise doğrulama başarısız olduğunda kullanıcıya dönecek özel mesajı belirler.

Bağımlılık Enjeksiyonu ile Entegrasyon

FluentValidation kurallarının uygulama genelinde otomatik olarak algılanması için, Program.cs dosyanızda servis kaydını yapmanız gerekir. Bu sayede, uygulamanızın herhangi bir yerinde doğrulama işlemini manuel olarak tetiklemek yerine, otomatik enjeksiyon avantajından yararlanabilirsiniz.

using FluentValidation;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

// Validator sınıflarının bulunduğu assembly'i tarar ve kaydeder
builder.Services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());

var app = builder.Build();

Bu işlem, projenizdeki tüm AbstractValidator türevlerini bulur ve IoC (Inversion of Control) konteynerine ekler. Böylece controller veya servis katmanlarınızda bu doğrulayıcıları kolayca kullanabilirsiniz.

Controller İçerisinde Doğrulama Kullanımı

Doğrulama katmanını oluşturduktan sonra, bunu API uç noktalarınızda kullanmanız gerekir. En temiz yöntem, IValidator arayüzünü kullanarak bağımlılığı enjekte etmek ve Validate metodunu çağırmaktır.

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly IValidator _validator;

    public UsersController(IValidator validator)
    {
        _validator = validator;
    }

    [HttpPost]
    public IActionResult Register(UserRegisterRequest request)
    {
        var result = _validator.Validate(request);
        if (!result.IsValid)
        {
            return BadRequest(result.Errors);
        }
        return Ok("Kayıt başarılı.");
    }
}

Bu yapı, gelen isteğin doğruluğunu kontrol eder. Eğer kurallara uyulmadıysa, result.Errors koleksiyonu üzerinden hataları JSON formatında istemciye döndürürüz.

Özel Doğrulama Kuralları Yazma

Hazır kurallar bazen karmaşık iş mantıklarını karşılamayabilir. Örneğin, veritabanında bir kullanıcı adının daha önce alınıp alınmadığını kontrol etmeniz gerekebilir. Bu durumda Must metodunu kullanarak özel bir mantık ekleyebilirsiniz.

RuleFor(x => x.Username).Must(BeUniqueUsername).WithMessage("Bu kullanıcı adı zaten alınmış.");

private bool BeUniqueUsername(string username)
{
    // Veritabanı kontrolü burada yapılır
    return _userRepository.GetByUsername(username) == null;
}

Bu yöntem, iş mantığınızı (business logic) doğrulama katmanına taşımanıza olanak tanır, ancak veritabanı işlemlerini asenkron yapmanız gerektiğini unutmayın.

Veri Doğrulama Yöntemlerinin Karşılaştırılması

Yöntem Avantajları Dezavantajları
Data Annotations Hızlı, basit, model üzerinde tanımlanır. Karmaşık kurallar için yetersiz, kod kirliliği yaratır.
FluentValidation Okunabilir, test edilebilir, ayrık mimari sunar. Ek kütüphane bağımlılığı, başlangıçta kurulum gerektirir.

Güvenlik Uyarısı: İstemci tarafındaki doğrulamalar asla tek başına yeterli değildir. FluentValidation ile yapılan sunucu tarafı doğrulamaları, SQL Injection ve XSS saldırılarına karşı bir savunma hattı olsa da, veritabanına kaydedilecek verilerin her zaman parametreli sorgularla işlendiğinden ve uygun şekilde temizlendiğinden emin olun.

Sıkça Sorulan Sorular

FluentValidation neden Data Annotations'dan daha iyidir?

FluentValidation, doğrulama mantığını model sınıfından ayırır (Separation of Concerns). Bu sayede model sınıflarınız temiz kalır ve karmaşık, çok adımlı doğrulama kurallarını yönetmek çok daha kolay hale gelir.

Doğrulama hatalarını nasıl özelleştirebilirim?

WithMessage metodu ile her kural için özel hata mesajları tanımlayabilir veya WithErrorCode ile hata kodları atayarak istemci tarafında yerelleştirme (localization) yapabilirsiniz.

Asenkron doğrulama yapabilir miyim?

Evet, MustAsync metodunu kullanarak veritabanı veya dış servis çağrıları gerektiren asenkron doğrulama kuralları tanımlayabilirsiniz.

Tüm validatörleri tek tek kaydetmek zorunda mıyım?

Hayır, AddValidatorsFromAssembly metodu ile tüm validatörleri tek bir satırla IoC konteynerine kaydedebilirsiniz.

Doğrulama hatalarını global olarak nasıl yönetirim?

ASP.NET Core'da ActionFilter veya Middleware kullanarak, her controller'da manuel kontrol yapmak yerine, tüm istekleri global bir doğrulama filtresinden geçirebilirsiniz.

FluentValidation ile İleri Seviye Senaryolar: CascadeMode ve RuleSet Kullanımı

FluentValidation, karmaşık iş kurallarını yönetmek için sadece basit doğrulama yöntemlerinden fazlasını sunar. Özellikle büyük ölçekli projelerde, doğrulama akışını kontrol etmek ve belirli senaryolara göre kuralları gruplandırmak, kodun okunabilirliğini ve performansını doğrudan etkiler.

CascadeMode ile Doğrulama Akışını Kontrol Etme

Varsayılan olarak FluentValidation, bir özellik için tanımlanan tüm kuralları çalıştırır. Ancak bazen, bir kural başarısız olduğunda sonraki kuralları çalıştırmayı durdurmak isteyebilirsiniz. CascadeMode özelliği ile bu davranışı yönetebilirsiniz.

public class UserValidator : AbstractValidator
{
    public UserValidator()
    {
        // Stop: İlk hata alındığında durur
        RuleFor(x => x.Email)
            .Cascade(CascadeMode.Stop)
            .NotEmpty()
            .EmailAddress();
    }
}

RuleSet ile Koşullu Doğrulama Grupları

Aynı modelin farklı durumlarda farklı kurallara tabi tutulması gerekebilir. Örneğin, bir kullanıcı kaydı sırasında şifre zorunluyken, güncelleme sırasında şifre alanı opsiyonel olabilir. Bu durumda RuleSet yapısını kullanmak en temiz çözümdür.

public class UserValidator : AbstractValidator
{
    public UserValidator()
    {
        RuleSet("Register", () => {
            RuleFor(x => x.Password).NotEmpty().MinimumLength(8);
        });

        RuleSet("Update", () => {
            RuleFor(x => x.FullName).NotEmpty();
        });
    }
}

FluentValidation ile Birim Testi (Unit Testing) Yazma

Doğrulama kurallarınızın doğru çalıştığından emin olmak için bunları birim testleri ile doğrulamak, özellikle karmaşık iş mantığı içeren projelerde kritik öneme sahiptir. FluentValidation.TestHelper kütüphanesi, bu süreci oldukça kolaylaştırır.

Öncelikle test projenize FluentValidation.TestHelper paketini ekleyin. Ardından, aşağıdaki gibi bir test senaryosu oluşturabilirsiniz:

using FluentValidation.TestHelper;
using Xunit;

public class UserValidatorTests
{
    private readonly UserValidator _validator = new UserValidator();

    [Fact]
    public void Should_have_error_when_Email_is_empty()
    {
        var model = new User { Email = "" };
        var result = _validator.TestValidate(model);
        result.ShouldHaveValidationErrorFor(x => x.Email);
    }

    [Fact]
    public void Should_not_have_error_when_Email_is_valid()
    {
        var model = new User { Email = "test@example.com" };
        var result = _validator.TestValidate(model);
        result.ShouldNotHaveValidationErrorFor(x => x.Email);
    }
}

Bu yaklaşım, kurallarınızı değiştirdiğinizde uygulamanızın geri kalanının bozulmadığından emin olmanızı sağlar. Testleriniz, validasyon mantığınız için bir dokümantasyon görevi de görür.

Sonuç

C# ile FluentValidation kullanarak veri doğrulama katmanı oluşturmak, uygulamanızın sürdürülebilirliğini ve kod kalitesini artırır. Doğrulama kurallarını merkezi bir yapıda toplamak, gelecekteki değişikliklerde size büyük zaman kazandıracaktır. Bir sonraki adım olarak, FluentValidation'ın sunduğu CascadeMode özelliğini inceleyerek, bir kural başarısız olduğunda diğerlerinin çalışıp çalışmayacağını kontrol etmeyi öğrenebilirsiniz.

Unutmayın, iyi bir yazılım mimarisi, hataları en erken aşamada yakalayan yapıdır. FluentValidation, bu hedefe ulaşmanızda en güçlü yardımcılarınızdan biri olacaktır.

Bu yazıya tepkinizi paylaşın:
Kerem Tekin

Teknik rehberler ve dijital araçların verimli kullanımı konusunda uzmanlaşmış bir editörüm. Karmaşık teknolojik süreçleri, herkesin kolayca uygulayabileceği rehberlere dönüştürerek zaman tasarrufu sağlamayı hedefliyorum.

Yorumlar (17)

17
okuyucu bu yazı hakkında yorum yaptı. Siz de deneyiminizi paylaşarak diğer okuyuculara yardımcı olabilirsiniz.
Caner Yılmaz
Caner Yılmaz 31 Temmuz 2026

Elinize sağlık hocam, uzun zamandır aradığım temiz mimari anlatımlarından biri olmuş. Custom validator kısmını da bir sonraki yazıda detaylandırabilir misiniz?

Kerem Tekin
Kerem Tekin 01 Ağustos 2026

Teşekkürler Caner! Custom validator konusu oldukça kapsamlı, kesinlikle önümüzdeki günlerde onun üzerine ayrı bir rehber hazırlayacağım.

Selin Başar
Selin Başar 02 Ağustos 2026

Ya ben kurulumda hata alıyom, package manager console üzerinden eklememe rağmen namespace gelmiyo. Çözemedim valla.

Oğuzhan Kaya
Oğuzhan Kaya 03 Ağustos 2026

Selin, projenin .csproj dosyasını kontrol ettin mi? Bazen paket yüklenmiş görünse de reference kısmında eksik kalabiliyor.

Burak Özdemir
Burak Özdemir 04 Ağustos 2026

FluentValidation candır ya. Projelerimde vazgeçilmezim oldu, kod kalabalığından kurtarıyo insanı. Paylaşım için sağol.

Zeynep Aksoy
Zeynep Aksoy 04 Ağustos 2026

Bu yöntemle validation'ları ayrı katmanda tutmak gerçekten büyük rahatlık. Peki performans konusunda çok büyük bir yük bindirir mi projeye?

Kerem Tekin
Kerem Tekin 05 Ağustos 2026

Zeynep, FluentValidation oldukça performanslı bir kütüphane. Çok uç seviyede bir mikroservis yapınız yoksa performans kaybını hissetmezsiniz bile.

Mertcan Şen
Mertcan Şen 05 Ağustos 2026

Anlatım güzel ama kod bloklarını kopyalarken bazen girintiler kayıyo, mobilden okurken biraz zorlandım.

Kerem Tekin
Kerem Tekin 06 Ağustos 2026

Geri bildirim için teşekkürler Mertcan, kod bloklarının responsive tasarımını tekrar gözden geçiriyorum.

Deniz Yıldırım
Deniz Yıldırım 05 Ağustos 2026

Entity Framework ile entegrasyonu hakkında da küçük bi örnek eklenseydi şahane olurdu aslında, yine de eline sağlık.

Emre Vural
Emre Vural 07 Ağustos 2026

Kesinlikle katılıyorum, EF ile kullanınca tadından yenmez olurdu.

Hakan Gürsoy
Hakan Gürsoy 06 Ağustos 2026

Harika özetlemişsin, yeni başlayanlar için çok açıklayıcı olmuş. Takipteyim.

Ayşegül Tekin
Ayşegül Tekin 06 Ağustos 2026

Yazıyı okudum ama hala anlayamadığım bir yer var, AbstractValidator sınıfını tam olarak ne zaman extend ediyoruz?

Kerem Tekin
Kerem Tekin 07 Ağustos 2026

Ayşegül, doğrulama kurallarını yazacağınız sınıfı oluşturduğunuz an extend etmeniz gerekiyor. Bu, FluentValidation'ın kuralları tanıması için şart.

Fırat Çelik
Fırat Çelik 07 Ağustos 2026

Dili çok akıcı kullanmışsın, teknik konuları anlatırken genelde çok boğucu oluyor ama bu sefer gayet keyifli okudum.

Selim Korkmaz
Selim Korkmaz 08 Ağustos 2026

Validation kurallarını Localization ile kullanmayı da anlatırsan çok makbule geçer, türkçe hata mesajları lazım oluyo bazen.

Ece Nur
Ece Nur 07 Ağustos 2026

Evet, localization konusu gerçekten çok önemli, onu atlamamak lazım.

Yorum Yaz