.Net Core Ortamında MediatR Pipeline Geliştirelim

Abdullah Öztürk
4 min readAug 19, 2022

--

Merhaba Arkadaşlar,

Bugün MediatR kapsamında gerçekleştirilen her bir istek için oluşturduğumuz genel yapıları (validation, logging vb) daha merkezi bir sisteme nasıl taşırız gibi soruların cevaplarına değineceğim. Genel tanımı yaptıktan sonra .NET Core ortamında bir uygulama geliştireceğiz.

MediatR kütüphanesinin ne işe yaradığını bilmiyorsanız buradaki yazımı okuyabilirsiniz.

Pipelines

Bir uygulamaya istek attığımız her isteğimize(request) karşın bir yanıt (response) döner. Yalnız bu request — response döngüsünde farkında olunmayan bir kısım var, pipelines. Pipelines sayesinde gönderilen istek birtakım operasyonlardan geçirilir ve eğer bir sıkıntı yoksa döngüye devam edilir. Bir problem meydana gelirse istek geri çevrilir ve response döndürülür. Aşağıda .NET Core pipeline mimarisinin yapısını görmektesiniz.

.Net Core Middleware Pipeline

Request ile gönderilen objeyi validasyondan geçirmek istediğimizi varsayalım. Bunun üstesinden nasıl gelirdik? Muhtemelen RequestHandler sınıfımız içerisinde aşağıdakine benzer bir kod yazar ve bu şekilde işlemin üstesinden gelirdik. Ancak çok fazla sınıfınızın olduğunu ve her seferinde bu kodu yazmak zorunda kaldığınızı düşünün.

Bunun yerine Pipelines ile her request için belli operasyonları geliştiren bir merkezi yapı oluşturarak daha temiz, daha güvenli, daha verimli bir çalışma ortamı elde edebiliyoruz.

Tanımı yaptığımıza göre yavaştan yapacağımız uygulama için hazırlıklara başlayalım. Öncelikle Domain katmanına gidelim ve Entities klasörü altında veritabanındaki tabloları temsil eden sınıfları oluşturalım.

Ayrıca asıl konudan sapmamak adına ayrıntılı bir şekilde oluşturduğum yapıları göstermeyeceğim. Yazının sonunda projenin linkini bulabilirsiniz.

BaseEntity ve Temel Entity Sınıflarımız

MediatR tarafında kullanacağımız request’e yanıt niteliğindeki response sınıfını oluşturalım.

Response Modelimiz

Application katmanına gelelim ve gerekli interface ve repository tanımlamalarını Interfaces klasörü altında gerçekleştirelim.

Entity sınıfları için Repository yapısı

Aynı katman içerisinde Validations için bir klasör oluşturalım ve içerisine ilgili event ile alakalı validasyon kurallarımızı yazalım. Aşağıda örnek olarak CreateNoteValidator kodları bulunmakta.

Configure metodu sayesinde zincirleme kurallarda tek bir mesaj dönmesini sağlayabiliyoruz.

Features klasörü oluşturalım ve CommandHandler ile QueryHandler sınıflarımızı MediatR aracılığıyla oluşturalım. Örnek olarak CreateNoteCommandHandler sınıfımız aşağıdaki gibi görünmektedir.

Fark ettiyseniz herhangi bir validasyon işlemine tabi tutmuyoruz. Bunun gibi işlemleri pipeline sayesinde kontrol ediyor olacağız.

Yazımızın en önemli kısmına geldik. Behaviour klasörü altında ValidationBehaviour adlı bir sınıf oluşturalım ve pipeline oluşturmaya yavaştan başlayalım.

ValidationBehaviour Genel Yapısı
  • Pipeline olması için IPipelineBehaviour interface’inden türetiyoruz
  • 2. ve 3. satırda bize gelen response ve request için kısıtlamalar getirerek dönecek ve gelecek veriyi belirtiyoruz.
  • Constructorda bu request’i kontrol edecek tüm validator sınıfları için bir dependency injection uyguluyoruz.
  • 14. satırda validator sınıfımız var mı diye kontrol ediyoruz. (GetAll isteği de yapılmış olabilir)
  • 16.satır ile 20.satırlar arasında bu request’e ait validator sınıflarının validate fonksiyonunu çağırarak validation response elde ediyoruz.
  • 22. satır ile 28. satırlar arasında response içerisindeki hataları kontrol edip eğer varsa ErrorResponse modelini ilk hata mesajı ile beraber döndürüyoruz.
  • 30. satırda eğer validasyona ihtiyacı olmayan bir request ise bir sıkıntı olmadığını belirterek operasyonun devam etmesini sağlıyoruz.

Hazır elimiz değmişken gelen isteğin türü ve istekle gelen parametreleri incelememiz açısından LoggingBehaviour sınıfını da oluşturalım.

LogginBehaviour Genel Yapısı
  • Pipeline olması için IPipelineBehaviour interface’inden türetiyoruz
  • 2. ve 3. satırda bize gelen response ve request için kısıtlamalar getirerek dönecek ve gelecek veriyi belirtiyoruz.
  • Constructorda tüm operasyonlara loglara dökmek için bir dependency injection uyguluyoruz.
  • 13. satırda gelen request’in typeof aracılığıyla tipini bulup metot adını logluyoruz.
  • 14. ve 22. satırlar arasında Reflection ile gelen request’e ait property’lerin içeriğini ve türlerini loglayabiliyoruz.
  • Son olarak geri dönüş değeri olarak belirttiğimiz response modelimizi logluyoruz ve operasyonun devam etmesini sağlıyoruz.

Artık Behaviour sınıflarımızı yazdığımıza göre bunları inject edelim ve API tarafındaki testlerimizi yapalım.

Application Katmanı Extension Metot

Presentation katmanında yani bizim projedeki API katmanında startup.cs üzerinde birkaç ayar yapmamız gerekiyor.

API dökümantasyonunu oluşturacağımız Swagger için de çeşitli ayarlar yapmış bulunmaktayız. Swagger hakkında kendinizi eksik hissediyorsanız buradaki yazımdan bilgilenebilirsiniz. Startup tarafındaki ayarlamalarımızı yaptığımıza göre Controller tarafını kodlamaya başlayabiliriz. Aşağıda asıl konudan kopmamak adına HttpPost metotlarını görmektesiniz.

Şimdi programımızı logları görmek açısından IIS Express üzerinden değil de CleanArch.API üzerinden başlatalım ve bir tane geçerli request objesi gönderelim ve logları gözlemleyelim. Sonrasında ise geçersiz bir request objesi gönderelim ve ValidationBehaviour sınıfını gözlemleyelim.

Veri başarıyla eklendi, şimdi loglarımızı inceyelim. Bakalım nasıl bir çıktı verdi?

Gördüğünüz gibi hangi request’in gönderildiği, hangi property’nin hangi değere sahip olduğu ve response türü gibi özellikleri yazdırabildik. Şimdi geçersiz bir request objesi gönderelim ve response modelini inceleyelim ve yazımızı sonlandıralım.

Evet, RequestHandler sınıfımızda herhangi bir validasyon kodu yazmasak da ValidationBehaviour sınıfı request objesi için bizim yerimize response döndü.

Bu yazımda pipeline nedir, tam olarak ne işe yarar ve MediatR implementasyonu nasıl gerçekleştirilir gibi soruların cevaplarını vermeye çalıştım.

Projeyi tam anlamıyla incelemek için github linkine buradan ulaşabilirsiniz.

Okuduğunuz için teşekkür ederim. Bir sonraki yazıda görüşmek dileğiyle.

--

--