Fluent Validation, Jeremy Skinner tarafından geliştirilen ve .NET için bir doğrulama kütüphanesidir. Formlar, API girişleri veya diğer veri modelleri üzerinde kolayca doğrulama kuralları tanımlamak için kullanılır.
Doğrulama kurallarını modelden ayırıp, ayrı doğrulayıcı (validator) sınıflar içerisinde akıcı (fluent) bir arayüz ile tanımlama yöntemidir. Bu sayede daha karmaşık senaryoları, koşullu ve dinamik doğrulamaları kolayca yönetebilirsiniz.
Bu yaklaşımda, doğrulama kuralları; Model sınıfından tamamen ayrılır, Ayrı bir validator sınıfı (genellikle AbstractValidator<T>
sınıfından türetilir) içerisinde tanımlanır, Zincirleme (chaining) metodlar kullanılarak okunabilir ve anlaşılır bir şekilde ifade edilir.
FluentValidation Kütüphanesi ile Doğrulama
FluentValidation kütüphanesi, .NET uygulamalarında model doğrulamasını gerçekleştirmek için güçlü ve esnek bir altyapı sunar. Aşağıda, FluentValidation’ın temel kullanım adımlarını ve yaygın metotlarını inceleyelim.
Kurulum: NuGet üzerinden projenize FluentValidation kütüphanesini ekleyin.
Install-Package FluentValidation
ASP.NET Core entegrasyonu için ayrıca şu paketi yükleyebilirsiniz.
Install-Package FluentValidation.AspNetCore
Temel Kullanım: Validator sınıfı oluşturma öncelikle, doğrulama uygulanacak modelimizi tanımlayalım.
public class User
{
public string Name { get; set; }
public string Email { get; set; }
public int Age { get; set; }
public string Password { get; set; }
}
Ardından, bu model için doğrulama kurallarını içeren bir validator sınıfı oluşturuyoruz.
using FluentValidation;
public class UserValidator : AbstractValidator<User>
{
public UserValidator()
{
// İsim alanı için kurallar
RuleFor(user => user.Name)
.NotEmpty().WithMessage("İsim boş olamaz.")
.MinimumLength(3).WithMessage("İsim en az 3 karakter olmalıdır.");
// Email alanı için kurallar
RuleFor(user => user.Email)
.NotEmpty().WithMessage("Email boş olamaz.")
.EmailAddress().WithMessage("Geçerli bir email adresi giriniz.");
// Yaş alanı için kurallar
RuleFor(user => user.Age)
.InclusiveBetween(18, 65).WithMessage("Yaş 18 ile 65 arasında olmalıdır.");
// Şifre alanı için düzenli ifade kontrolü
RuleFor(user => user.Password)
.Matches(@"^(?=.*[A-Z])(?=.*\d).{6,}$")
.WithMessage("Şifre en az 6 karakter, bir büyük harf ve bir rakam içermelidir.");
}
}
Bu örnekte kullanılan metotlar:
- RuleFor: Belirli bir özellik için doğrulama zincirini başlatır.
- NotEmpty & NotNull: Alanın boş veya null olmamasını sağlar.
- MinimumLength, MaximumLength, InclusiveBetween: String uzunluk veya sayısal değer aralıkları kontrolü sağlar.
- EmailAddress & Matches: Format kontrolleri için kullanılır.
- WithMessage: Hata mesajını özelleştirir.
1. Temel Validation Fluent API Metotları
NotEmpty(): Bir özelliğin null, boş veya yalnızca boşluk karakterlerinden oluşmadığını doğrular.
RuleFor(user => user.Name)
.NotEmpty()
.WithMessage("İsim boş olamaz.");
NotNull(): Bir özelliğin null olmadığını kontrol eder (boş string yine de kabul edilebilir).
RuleFor(user => user.Description)
.NotNull()
.WithMessage("Açıklama null olmamalıdır.");
Length(min, max): Bir string özelliğin uzunluğunun belirlenen minimum ve maksimum değerler arasında olduğunu garanti eder.
RuleFor(user => user.Password)
.Length(6, 12)
.WithMessage("Şifre 6 ile 12 karakter arasında olmalıdır.");
InclusiveBetween(min, max): Bir özelliğin değerinin, belirlenen alt ve üst sınırlar dahil olmak üzere bu aralıkta olduğunu doğrular.
RuleFor(user => user.Age)
.InclusiveBetween(18, 65)
.WithMessage("Yaş 18 ile 65 arasında olmalıdır.");
ExclusiveBetween(min, max): Bir özelliğin değerinin, belirtilen sınır değerler hariç olmak üzere, bu aralıkta olduğunu doğrular.
RuleFor(user => user.Score)
.ExclusiveBetween(0, 100)
.WithMessage("Puan 0 ile 100 arasında, sınırlar hariç olmalıdır.");
GreaterThan(value): Bir özelliğin değerinin verilen değerden kesinlikle büyük olduğunu kontrol eder.
RuleFor(user => user.ExperienceYears)
.GreaterThan(0)
.WithMessage("Deneyim yılı 0'dan büyük olmalıdır.");
GreaterThanOrEqualTo(value): Özelliğin değerinin belirtilen değerden büyük veya eşit olduğunu doğrular.
RuleFor(user => user.Salary)
.GreaterThanOrEqualTo(3000)
.WithMessage("Maaş en az 3000 TL olmalıdır.");
LessThan(value): Özelliğin değerinin verilen değerden kesinlikle küçük olduğunu kontrol eder.
RuleFor(user => user.Discount)
.LessThan(50)
.WithMessage("İndirim %50'den az olmalıdır.");
LessThanOrEqualTo(value): Özelliğin değerinin belirlenen değerden küçük veya ona eşit olduğunu doğrular.
RuleFor(user => user.Rating)
.LessThanOrEqualTo(5)
.WithMessage("Puan 5'ten yüksek olamaz.");
2. String Validation Fluent API Metotları
Matches(regex): Bir string özelliğin, verilen düzenli ifadeye (regex) uyduğunu doğrular.
RuleFor(user => user.Password)
.Matches(@"^(?=.*[A-Z])(?=.*\d).{6,}$")
.WithMessage("Şifre en az bir büyük harf ve bir rakam içermelidir.");
EmailAddress(): Bir string özelliğin geçerli bir e-posta adresi formatında olduğunu kontrol eder.
RuleFor(user => user.Email)
.EmailAddress()
.WithMessage("Geçerli bir email adresi giriniz.");
MaximumLength(max): Bir stringin maksimum karakter uzunluğunu sınırlar.
RuleFor(user => user.Username)
.MaximumLength(20)
.WithMessage("Kullanıcı adı en fazla 20 karakter olabilir.");
MinimumLength(min): Bir stringin minimum karakter uzunluğunu kontrol eder.
RuleFor(user => user.Username)
.MinimumLength(3)
.WithMessage("Kullanıcı adı en az 3 karakter olmalıdır.");
NotEqual(value): Bir özelliğin değerinin, belirtilen değere eşit olmadığını doğrular.
RuleFor(user => user.Username)
.NotEqual("Admin")
.WithMessage("Kullanıcı adı 'Admin' olamaz.");
StartsWith(value): Bir string özelliğin, belirtilen alt dizeyle başladığını doğrular.
RuleFor(user => user.Code)
.StartsWith("PRD")
.WithMessage("Kod 'PRD' ile başlamalıdır.");
EndsWith(value): Bir string özelliğin, belirtilen alt dizeyle bittiğini doğrular.
RuleFor(user => user.FileName)
.EndsWith(".jpg")
.WithMessage("Dosya adı '.jpg' ile bitmelidir.");
3. Custom Validation Fluent API Metotları
Must(condition): Özelliğe özel senkron (synchronous) bir koşul tanımlayarak doğrulama yapılmasını sağlar.
RuleFor(user => user.Age)
.Must(age => age % 2 == 0)
.WithMessage("Yaş çift bir sayı olmalıdır.");
MustAsync(asyncCondition): Özelliğe özel asenkron (asynchronous) bir koşul tanımlamak için kullanılır.
RuleFor(user => user.Email)
.MustAsync(async (email, cancellation) => await EmailIsUnique(email))
.WithMessage("Bu email adresi zaten kullanılıyor.");
WithMessage(message): Herhangi bir doğrulama kuralı başarısız olduğunda dönecek özel hata mesajını belirler.
RuleFor(user => user.Name)
.NotEmpty()
.WithMessage("İsim bilgisi gereklidir.");
Custom(): Birden fazla özelliği içeren veya standart metotların dışında özel bir doğrulama işlemi yapmanızı sağlayan senkron metottur.
Custom(user => {
if(user.StartDate > user.EndDate)
{
return new ValidationFailure("StartDate", "Başlangıç tarihi bitiş tarihinden sonra olamaz.");
}
return null;
});
CustomAsync(): Özellikle IO işlemleri veya asenkron kontroller gerektiren karmaşık doğrulamalar için kullanılan asenkron metottur.
CustomAsync(async (user, cancellation) => {
if(!await CheckUserEligibility(user.Id))
{
return new ValidationFailure("Id", "Kullanıcı uygun değil.");
}
return null;
});
4. Conditional Validation Fluent API Metotları
When(): Belirtilen koşul doğru olduğunda ilgili doğrulama kuralının çalışmasını sağlar.
RuleFor(user => user.Email)
.NotEmpty()
.WithMessage("Email boş olamaz.")
.When(user => user.IsEmailRequired);
Unless(): Belirtilen koşul yanlış olduğunda doğrulama kuralının uygulanmasını sağlar.
RuleFor(user => user.Nickname)
.NotEmpty()
.WithMessage("Takma ad boş olamaz.")
.Unless(user => string.IsNullOrEmpty(user.Name));
5. Chaining Rules
Tek bir özellik için birden fazla doğrulama kuralının zincirleme olarak (fluent) yazılmasını sağlar.
RuleFor(user => user.Username)
.NotEmpty().WithMessage("Kullanıcı adı gereklidir.")
.Length(5, 50).WithMessage("Kullanıcı adı 5 ile 50 karakter arasında olmalıdır.")
.NotEqual("Admin").WithMessage("Kullanıcı adı 'Admin' olamaz.");
6. Validation for Complex Types
SetValidator(): Bir nesnenin (modelin) içindeki başka bir nesnenin doğrulamasını, o nesneye ait ayrı bir doğrulayıcıya devreder.
public class Address
{
public string City { get; set; }
public string PostalCode { get; set; }
}
public class AddressValidator : AbstractValidator<Address>
{
public AddressValidator()
{
RuleFor(a => a.City)
.NotEmpty().WithMessage("Şehir bilgisi gereklidir.");
RuleFor(a => a.PostalCode)
.NotEmpty().WithMessage("Posta kodu gereklidir.");
}
}
public class User
{
public string Name { get; set; }
public Address Address { get; set; }
}
public class UserValidator : AbstractValidator<User>
{
public UserValidator()
{
RuleFor(user => user.Name)
.NotEmpty().WithMessage("İsim bilgisi gereklidir.");
RuleFor(user => user.Address)
.SetValidator(new AddressValidator());
}
}
7. Collection Validation
ForEach(): Bir koleksiyon özelliğindeki her bir eleman için tanımlanan doğrulama kurallarını uygular.
public class Order
{
public List<string> Items { get; set; }
}
public class OrderValidator : AbstractValidator<Order>
{
public OrderValidator()
{
RuleForEach(order => order.Items)
.NotEmpty().WithMessage("Her bir ürün bilgisi boş olamaz.")
.MinimumLength(3).WithMessage("Ürün adı en az 3 karakter olmalıdır.");
}
}