Fluent Validation (.NET Validation İşlemleri)

İster web, ister mobil bir uygulama yazalım, geliştirdiğimiz uygulama yüzlerce hatta binlerce kişi tarafından kullanılabilir. Özellikle bu kullanıcı kitlesi içerisinde kötü niyetli kişilerin de olabileceğini düşünürsek kullanıcılardan aldığımız verilerin doğruluğu bizim açımızdan büyük önem arz etmektedir. jQuery Validation veya alternatif javascript kütüphaneleri ile bu sorunun önüne geçsek dahi bu doğrulamalar Javascript tabanlı yapıldığından tam güvenlik sağlayamazlar. Uygulamamıza dışarıdan  (get-post vb.) talep gelebileceğinden veya Javascript kapatılabileceğinden client-side olarak yapılan hiç bir doğrulama yöntemine güvenemeyiz.

javascript kapatmak

.NET tarafında model bazlı doğrulamalar için genellikle Data Annotations kullanılmaktadır. Bu makalede uzun zamandır kullandığım Fluent Validation kütüphanesinden bahsedeceğim. Jeremy Skinner tarafından 2008 yılından bu yana geliştirilen kütüphane dünya genelinde de oldukça popüler.

Github: https://github.com/JeremySkinner/FluentValidation

Fluent Validation kütüphanesi Data Annotations alternatifi olmayıp  birlikte de uyum içerisinde çalışmaktadır. Örneğin propertyler için verilen DisplayName işlemi yine Data Annotations üzerinden yapılmaktadır.

Not: Fluent Validation’ın henüz .Net Core 1.0 desteği bulunmamakta, geliştirici tarafından ilgili desteğin .Net Core 1.0 RC2 sürümünden itibaren geleceği söylendi.

Fluent Validation ile hem server-side hem de client-side doğrulamalar yapabilirsiniz. Client-side için jQuery Validation ve jQuery Validation Unobtrusive kütüphanelerine ihtiyacımız olacak. Başlangıç olarak server-side doğrulamayı anlatıp makalenin sonlarına doğru ise client-side doğrulamaya değineceğim.

Anlatacağım örnekte bir öğrenci kaydı alıp ve daha sonra güncellemesi yapılacakmış gibi kurgulayacağız. Aynı model için kayıt ve güncelleme esnasında farklı doğrulama kuralları çalıştırarak Fluent Validation’ın kullanışlı özelliklerinden de bahsedeceğim.

Ogrenci.cs adında bir class oluşturalım ve aşağıdaki propertyleri ekleyelim.

public class Ogrenci
{
public int OgrenciId {get; set;}
public int OgrenciNo { get; set; }
public string AdSoyad { get; set; }
public string Sifre { get; set; }
public string SifreTekrar { get; set; }
public string Eposta { get; set; }
}

Ogrenci.cs classımızı oluşturduktan sonra projemize gelip Nuget Package Manager üzerinden Fluent Validation kütüphanesini kuralım.

fluent validation

Kurulum işlemi sonrasında references altında FluentValidation.dll ‘ i görünecektir.

Şimdi gelelim ikinci aşamaya. Ogrenci sınıfımız için bir de validate işlemini yapacağımız bir class’a ihtiyacımız var. İstersek aynı dosya içerisine, istersek farklı dosyalar içerisine yazabiliriz. Bağımlılığı azaltmak adına ayrı bir OgrenciValidator.cs adında bir class daha oluşturalım ve hemen ilk iş usinglerimizin arasına FluentValidation’ı ekleyelim.

using FluentValidation;

Bu sayfada Ogrenci classımızın validate işlemlerini gerçekleştireceğiz. Bunun için FluentValidation kütüphanesi içerisinde bulunan AbstractValidator<> sınıfını kalıtım (miras) yoluyla classımıza dahil edelim. Generic yapıda olduğundan içerisine Ogrenci sınıfını alacak.

public class OgrenciValidator : AbstractValidator<Ogrenci>

Aşağıdakine benzer bir yapı oluşacak;

fluent validation

Doğrulama senaryom şu şekilde olacak:

  • AdSoyad alanı boş olamaz ve en az 4, en fazla 50 karakter olabilir.
  • OgrenciNo alanı 100 ile 1000 arasında olmalı.
  • Eposta alanı boş olabilir ancak doluysa e-posta formatına uymak zorunda.
  • Şifre ve Şifre tekrar alanları boş olamaz ve aynı olmak zorundadır. Eğer OgrenciId sıfırdan farklı ise (yani update/güncelleme işlemi yapılıyorsa)  bu alanlar boş olabilir.

Son maddeye dikkat edersek iki farklı durum söz konusu. Validation işlemi gelen verinin yapısına göre (yeni kayıt/güncelleme) şekil değiştirecektir.

Öncelikle bir OgrenciValidator classımızın içerisinde bir Constructor oluşturalım ve kurallarımızı yazmaya başlayalım. Mapping işlemleri Fluent API kullananlar için tanıdık gelecektir, neredeyse birebir.

public OgrenciValidator()
{
RuleFor(x => x.AdSoyad).NotEmpty().WithMessage("Öğrenci adı boş olamaz.")
 .Length(4, 50).WithMessage("Öğrenci adı 4 ile 50 karakter arasında olmalıdır.");

 RuleFor(x => x.OgrenciNo).GreaterThan(100).WithMessage("ÖğrenciNo 100 den büyük olmalıdır.")
 .LessThan(1000).WithMessage("Öğrenci 1000 den küçük olmalıdır.");

 RuleFor(x => x.Eposta).EmailAddress().WithMessage("Geçerli bir eposta adresi giriniz.").When(x => !string.IsNullOrEmpty(x.Eposta));

 RuleFor(x => x.Sifre).Equal(x => x.SifreTekrar).WithMessage("Şifreler eşleşmiyor.");
 RuleFor(x => x.Sifre).NotEmpty().WithMessage("Şifre boş olamaz.").When(x => x.OgrenciId == 0);
}

Validator classımızın son hali;

fluent validation

 

Buraya kadar her şey tamam. Ogrenci classımızı ve onun için validate işlemini yapacak classımızın kurallarını tamamladık. Şimdi yazdıklarımızı test etme zamanı.

Ogrenci ogrenci = new Ogrenci
{
AdSoyad = "Sinan BOZKUŞ",
Eposta = "sinan.bozkus@bilgeadam.com",
OgrenciNo = 3000,
DogumYili = 1988,
Sifre = "123456",
SifreTekrar = "123456"
};

OgrenciValidator validator = new OgrenciValidator();

ValidationResult result = validator.Validate(ogrenci);

if(result.IsValid)
{
// Geçerli öğrenci modeli, validation'dan geçti.
}
else
{
// Geçersiz öğrenci modeli, validation'a takıldı.
}

ValidationResult için “using FluentValidation.Results;” eklemeniz gerekmektedir.

Yukarıdaki kod çalıştığında result.IsValid sonuç olarak  false dönecektir çünkü öğrenci no 1000’den küçük olmak zorundadır.

Örneğimizde Fluent Validation’ın kısaca nasıl kullanıldığını öğrendik. Bağımsız bir validation yapısı oluşturduğumuz için Ogrenci classımız için birden fazla validator oluşturabilir ve bu class için farklı formlarda farklı validationlar uygulayabiliriz.

Fluent Validation’ın nasıl kullanıldığını öğrendiğimize göre web uygulamamıza entegre etmeye hazırız. (ASP.NET MVC yapısına uygun şekilde anlatacağım.)

İlk iş gerekli Javascript kütüphaneleri sayfamıza ekliyoruz.
(Kendi sunucunuzdaki dosya yoluna göre düzenlemeniz gerekiyor…)


<script src="~/Scripts/jquery.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

fluent validation form

Kullanacağım form yukarıdaki resimdeki gibi olacaktır.

İlk senaryomda veriler form’dan  POST ile Controller’ıma düşecek ve ben burada validation işlemlerini yaptıktan sonra tekrar form’ a döneceğim.


[HttpPost]
 public ActionResult Yeni(Ogrenci formData)
 {
 OgrenciValidator validator = new OgrenciValidator();

ValidationResult result = validator.Validate(formData);

if (result.IsValid == false)
 {
 foreach (var error in result.Errors)
 {
 ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
 }
 return View();

}

return View();
 }

Yukarıda yapılan işlemleri kısaca özetlemek gerekirse form’dan gelen nesnemiziFluent Validation ile kontrol ediyoruz ve result nesnemiz de oluşan tüm Errorları ModelState’e ekleyerek form’a geri gönderiyoruz. Form’da bulunan ValidationMessage alanlarında bu hatalar görünecektir.

fluent validation form error

Mevcut senaryomuzda sunucuya post işlemi yapıldı ve validation işlemi server-side yapılarak tekrar client’a dönüş yapıldı. Aktif kullanıcı sayısı düşük olan sistemlerde önemsenmeyecek bir durum olsa da aktif kullanıcı sayısı yüksek sistemler için can sıkıcı bir durum oluştu. Eğer Data Annotations kullandıysanız ilgili validationların Entityler ile birebir ilişkilendirildiğini ve client-side’a yansıdığını fark etmişsinizdir. Burada da yapmamız gereken oluşturduğumuz validation classını mevcut Ogrenci classımız ile ilişkilendirmek.

Bunun için yapmamız gereken aşağıdaki kodu Ogrenci class’ımızın üzerine ekleyerek Ogrenci Class’ımızın Validate işlemlerinin UserValidator tarafından yürütülmesini sağlamak.

[Validator(typeof(UserValidator))]

fluent validation

Class ile ilişkilendirme işlemimizi tamamladıktan sonra projemize (birden fazla katmanlı çalışıyorsanız sadece web/mvc katmanına) nuget package manager üzerinden “FluentValidation.MVC” kütüphanesini indiriyoruz.. (Mevcut Fluent Validation kurulumuza eklenti olarak çalışacaktır.)

fluent_validation5

Global.asax dosyamızı açıyoruz ve aşağıdaki işlemleri yapıyoruz.

usinglerimiz arasına

using FluentValidation.Mvc;

Application_Start() içerisine

FluentValidationModelValidatorProvider.Configure();

ekliyoruz.fluent_validation_6

 

Bu işlemden sonra hem client-side hem de server-side çift taraflı validation işlemi yapmaktayız.

Makalemizin sonuna geldik. Bu bilgiler ile bir proje de Fluent Validation’ı rahatlıkla kullanabilir ve tüm validation işlemlerini Fluent Validation üzerinden yürütebilirsiniz.

Sinan Bozkuş

 

 

  1 Comment

  1. Yyy   •  

    Data Annotation olduğu zaman fluent validation devreye girmiyor. İkisinin birlikte çalışabildiği bir örnek gösterebilir misiniz?

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir