.Net Core Eğitimleri

14- ) JWT Token ile Login

JWT Token

Haberleşme ihtiyacı duyan 2 ya da daha fazla sistem arasında güvenliği sağlamak ve veri taşımak amacı ile kullanılır. Jwt token json veri yapısını kullanır, url ile taşınabilir, cookie ihtiyacını ortadan kaldırır  ve HTTP session gereksinimi zorunlu olmaktan çıkarır. Jwt token oluşturmak için güvenlik kodu, expire tarihi ve body diyebileceğimiz bilgileri barındıran kısımın belirlenmesi temel olarak yeterli olacaktır. Güvenlik kodu bu tokenin doğruluğunun anlaşılabilmesi için gereklidir ve gizli olmalıdır. Token bu güvenlik key ile oluşturulur ve çözümleme yapılırken bu güvenlik key den yararlanılır. Expire tarihi ne zamana kadar geçerli olduğu bilgisini tutar. Geri kalan kısımda ise token içine eklenmek istenen veriler yer alacaktır.

JWT Token’in Projeye Eklenmesi

Kullanıcılar sistemimiz üzerinde oturum açmak istediklerinde, girdikleri kullanıcı adı ve parolayı kontrol edecek ve doğru bilgiler ile giriş yapılmak isteniyor ise bu kullanıcıya özel bir token oluşturacağız. Kullanıcı token aldıktan sonra her request’i için header alanında bu tokeni göndererek apimiz üzerindeki fonksiyonları kullanabilecek. Jwt token ile login işlemleri yapmak için aşağıdaki şekilde gerekli dosyaları oluşturalım.

Öncelikle gerekli modelleri oluşturacağız. Bunun için WebApi projesinde bulunan VM klasörüne sağ tıklayarak Add–>Class yolunu izleyerek sırası ile LoginModel ve TokenModel isminde iki adet sınıf oluşturalım, daha sonra içeriklerini aşağıdaki şekilde düzenleyelim.

LoginModel.cs

TokenModel.cs

Daha sonra WebApi projemizden bulunan Interfaces klasörüne sağ tıklayalım ve Add –> Class yolunu izleyerek ITokenController isminde bir dosya oluşturalım. Daha sonra bu dosyanın içeriğini aşağıdaki şekilde düzenleyelim. Token controllerımızın içermesi gereken metotları bu interface ile belirlemiş olduk.

Şimdi Controller klasörüne sağ tıklayalım ve Add –> Class diyerek TokenController isminde bir dosya oluşturalım. Daha sonra bu dosyanın içinide aşağıdaki şekilde düzenleyelim.

Yukarıdaki işlemleri yaptığınızda sıra appsettings.json dosyasını düzenlemeye geldi. WebApi projesi içinde bulunan dosyayı açarak içeriğini aşağıdaki şekilde düzenleyelim.

Connection string’i, Issuer kısmını kendi bilgileriniz ile güncellemeyi unutmayın.

Son olarak WebApi projesinde bulunan Startup.cs dosyasını açalım ve ConfigureServices metodunun içinde en üst kısma aşağıdaki kodu yazalım.

Token sınıfı haricinde kalan sınıflara token olmadan erişimi kısıtlamak için ilgili sınıfları açarak class tanımlamalarının üzerine aşağıdaki kodu ekleyebilirsiniz.

Roles kısmını silerseniz tokeni olan herkes o sınıfa erişebilir, rol kısmındaki bilgiyi sistemde roles tablosunda kayıtlı bilgilerden seçerek tekli ya da çoklu şekilde yazabilirsiniz.

Tüm işlemleri bitirdiğinizde sisteminize login ve rol kontrolü yeteneklerini eklemiş olacaksınız.

Projenin buraya kadar olan kısmı ile ilgili sorun yaşıyorsanız bu link ile github üzerinden projeyi indirebilir ve kendi yazdığınız kodlar ile karşılaştırabilirsiniz. Sorularınız için yorum kısmını kullanabilir ya da mail adresim üzerinde benimle iletişime geçebilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

13- ) Cache Alt Yapısı

Cache İşlemleri

Bu derste projemize cache yeteneği ekleyeceğiz.  Sıklıkla değişikliğe uğramasını beklemediğimiz verileri cache de yani önbellekte hazır olarak tutabiliriz, bu bize performans kazandıran bir işlem olur ancak getirilerinin yanında götürüleri de tabiki olacaktır.

Cache birden fazla yöntemle birden fazla şekilde yapılabilir. Daha önceki yazılarımda da belirttiğim gibi, yazılım geliştirirken hangisi en iyi ya da hangisi tercih edilmeli soruları için mutlaka öncesinde bir strateji belirlenmeli ve ona göre seçim yapılmalı. Cache işlemi içinde bu durum geçerli.

Memory Cache (Server Side)

Sunucunun belleklerinde belirli bir süre için veri saklama işlemidir. Veriler belirtilen kurallara göre (ne kadar süreliğine, hangi anahtar ile .. vs) bellek üzerinde hazır olarak bekletilir. İstemciler bu verilere ulaşmak istediğinde, sistem öncelikle bellekte bu verilerin olup olmadığını kontrol eder ve yok ise ancak o zaman veritabanı ya da fiziki veri saklama alanına gider.

Verilerin hazır olarak bekletilmesi bize doğru kurgulandığında ciddi performans kazancı sağlayacaktır, hem istemciler ile sunucu arasında trafik rahatlayacak hemde iç sistemler arası trafik azalacaktır. Ancak gereksiz yere çok büyük verilerin bellek üzerinde tutulması, sunucu kaynaklarının aşırı kullanılması sebebi ile geç yanıt vermelere ve hatta kilitlenmelere neden olabilir. Artılar ve eksiler göz önünde bulundurulmalı, uygulamanın koşacağı sunucu iyi seçilmeli ve aynı sunucuda başka uygulamalar koşacak ise bu uygulamalarında davranışsal özellikleri iyi anlaşılmalıdır.

Response Cache

Memory cache yönteminden farklı olarak bu yöntemde bir middleware görev yapar ve eğer son response’un httpstatus’u 200 yani başarılı ise ve veriler belirtilen özelliklere göre cachelenmiş ise, uygulamadaki action ya da metod tetiklenmez.

Sürekli değişkenlik gösteren veriler üzerinde bu işlemi yapmak sorunlara neden olabilir bu nedenle yine iyi analiz edilerek doğru şekilde uygulanması gerekir. Tarayıcılarda yenileme işlemi yapıldığında cache’den okuma yapılmadan doğrudan ilgili metod call edilir bu nedenle uygulama içi redirect işlemleri yapılırken bu durum göz önüne alınmalıdır.

Distributed Cache

Bu yöntem 3. parti bir yazılım gerektirmektedir. Paylaşılan ortak bir cache alt yapısı kurulmak istendiğinde bu yöntem tercih edilmelidir. Birden fazla uygulama ya da sistem aynı verileri cachelemeye ve o cache pool üzerinde işlemler yapmaya ihtiyaç duyuyor ise distributed cache kullanabilir. Bu konu için Microsoft Velocity ya da redis gibi uygulamaları araştırabilirsiniz.

Projeye Memory Cache ve Response Cache Eklenmesi

Projemizde bulunan ve çoklu dil desteği için kullanacağımız AppResource tablosundaki verilerin çok fazla değişmeyeceği senaryosu üzerinden devam ederek bu entity ile ilgili controllerımız üzerinde hem Memory Cache hem de Response cache alt yapısını kuracağız.

Öncelikle WepApi projemizin içinde bulunan Startup.cs dosyasını aşağıdaki şekilde düzenleyelim. Kodun içinde CacheSection şeklinde adlandırılmış regionları kontrol edelim, bu kısımda yazılan kodlar bizim projemizde bu özellikleri kullanacağımızı söylediğimiz ve ayarlamaları yaptığımız yerler.

Statup.cs dosyası içinde çeşitli cache profilleri oluşturabilir ve bunları kullanabilirsiniz, ya da istemciye döneceğiniz her türlü cevabı cacheleyecekseniz bu kısımda genel bir cache tanımlaması yapabilirsiniz. Aşağıda sadece cache alt yapısı parametresiz olarak çağırılıyor ve default özellikler ile projeye dahil edilmesi bekleniyor.

Memory cache için microsoft’un sitesinde bulunan detaylı anlatıma bu link ile ve response cache ile ilgili anlatımlara ise bu link ile erişebilirsiniz.

Daha sonra AppResourceController’ı aşağıdaki şekilde düzenliyoruz ve sistemimize cacheleme özelliğini de eklemiş oluyoruz.

Tarayıcı üzerinde bu metodu test edip F12 tuşuna basarak network kısmında headerları inceleyebilirsiniz. Dikkat etmeniz gereken en önemli nokta sayfa yenileme yaparsanız cacheden okuma işlemi gerçekleşmez yeni sekmelerde aynı url i açarsanız header kısmında httpstatus alanının yanında from local disk yazısını görebilirsiniz.

Projenin buraya kadar olan kısmı ile ilgili sorun yaşıyorsanız bu link ile github üzerinden projeyi indirebilir ve kendi yazdığınız kodlar ile karşılaştırabilirsiniz. Sorularınız için yorum kısmını kullanabilir ya da mail adresim üzerinde benimle iletişime geçebilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

12- ) Entity Framework – Lazy Loading

Lazy Loading

Bundan önceki derslerde Entity Framework kullanarak nasıl custom şekilde Include işlemleri yapacağımızı gördük. Include işlemini birbiri ile ilişkili tabloların verilerini aynı model içinde göstermek için kullanıyoruz, bir nevi sql üzerinde join işlemi yapmak gibi de düşünebilirsiniz. Farketti iseniz getall, find ve getallwithpaging gibi kayıt çekmek için kullandığımız metodlar var ve biz ilişkili tablolarda bu metodları kullanmak için ilgili controllerda override ederek gerekli bağımlılıkları yani diğer tabloları modele include ettik. Peki her seferinde bu şekilde uğraşacakmıyız? Cevap stratejinize ve kurgunuza göre değişsede her seferinde uzun uzun bu işlemleri yapmak zorunda değilsiniz Lazy loading özelliği bizim için bu işi otomatik olarak yapabilir.

Eğer sisteminizde bulunan ilişkisel tabloların yapısı 3 ya da 4 kat aşağıya inmiyorsa yani örnek vermek gerekirse, Customer içinde organization bilgisi onun içinde ilçe bilgisi onun içinde il bilgisi, ilin içinde ülke bilgisi, … vs gibi alt alta giden bir çok kırılımınız yok ise ve ya gerekli donanımsal kaynaklarınız var ise lazy loading yapısını kullanabilirsiniz. Lazy loading sizin entityleriniz içinde bulunan virtual şeklinde tanımlanmış diğer entity referanslarınızı override ederek içlerini otomatik olarak doldurur. Yani sizin Customer tablonuz içinde virtual olarak tanımlanmış bir organization entity referansı/property si var ise lazy loading onu otomatik olarak ilişkili kayıt ile dolduracaktır.

Artıları

  • Her seferinde include işlemi yapmanıza gerek kalmaz
  • Gerekli tüm bağımlılıkları otomatik olarak aldığı için istemcinin veriye erişmesi kolaylaşır

Eksileri

  • Karmaşık ilişkilere sahip mimarilerde uzun bekleme sürelerine yol açabilir
  • İhtiyacınız olmadığı senaryolarda bile tüm ilişkisel alanlar dolar

Bunlara daha fazla madde eklenebilir ancak en belirgin ve yalın hali ile bu şekilde ifade edilir. Bu özelliği kullanıp kullanmamak tamamı ile sizin senaryolarınıza ve stratejilerinize kalmışdır.

Peki Nasıl Kullanacağız?

Öncelikle “Microsoft.EntityFrameworkCore.Proxies” nuget paketini Data katmanımıza ekleyeceğiz. Bunun için Data projesine solution explorer üzerinden sağ tıklayarak manage nuget packages seçeneğine tıklayalım. Daha sonra arama kımına  “Microsoft.EntityFrameworkCore.Proxies” yazalım ve çıkan paketi seçerek Install tuşuna basalım. Daha önceki derslerde nuget paketlerinin nasıl sisteme eklendiğini detaylıca görmüştük, sorun yaşar iseniz önceki derslere bakabilirsiniz. Paketi projeye ekledikten sonra SolutionExplorer üzerinden Context klasörü altında bulunan ApplicationDbContext.cs dosyamıza çift tıklayalım ve içeriğini aşağıdaki şekilde düzenleyelim.

Artık projemize Lazy loading özelliğini eklemiş olduk. Şimdi dilerseniz override ettiğimiz find,getall metotlarını controllerların içinde yorum satırına alalım. Böylece her iki yöntemde bu projenin içerisinde kalmış olacak, isterseniz lazy loading ile ilgili olan 54. satırı silebilir, controllerlarda bulunan override kodları yorum satırı halinden çıkarabilir ve eskisi gibi çalışmaya devam edebilirsiniz. Ben CustomerController üzerinde bulunan find ve getall metodlarını yorum satırı haline aşağıdaki şekilde getirdim.

Peki şimdi postman üzerinde bir test yapalım ve bakalım organization bilgileri otomatik olarak gelecek mi?

Lazy loading testi
Lazy loading testi

Gördüğünüz gibi dönen json cevabı içerisinde organization sekmesi altında ilişkili olan kayıt otomatik olarak doldu.

Projenin buraya kadar olan kısmı ile ilgili sorun yaşıyorsanız bu link ile github üzerinden projeyi indirebilir ve kendi yazdığınız kodlar ile karşılaştırabilirsiniz. Sorularınız için yorum kısmını kullanabilir ya da mail adresim üzerinde benimle iletişime geçebilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

11- ) Web Api Projesi 2. Kısım

Web Api 2. Kısım

Bu dersimizde web api projemizin diğer controller larını oluşturarak, auto history  alt yapısına loglama emrini verecek düzenlemeleri yapacağız. Geliştirdiğimiz web api projesini postman istemcisi ile test ederek güncellediğimiz ya da sildiğimiz kayıtların auto history ile nasıl saklandığına bakacağız.

Controllerlar

Öncelikle controllerlarımızın uygulayacağı interfacelerimizi oluşturacağız daha sonra controllerları oluşturarak içlerini düzenleyeceğiz. Adım adım aşağıdaki şekilde işlemleri yapalım ve projemize controllerlarımızı ekleyelim.

Bir önceki derste UserController’a giriş yapmış ve sadece kullanıcı ekleme işlemi gerçekleştirmiştik. Şimdi kullanıcı ile ilgili tüm işlemleri aşağıdaki şekilde kodlayacağız ancak onun öncesinde web api projemizin içine yeni bir klasör oluşturarak adına VM diyelim. Tam olarak view model olmasada burada kullanıcıdan veri almak için model tanımlamalarımızı yapacağız. Daha sonra bu klasöre sağ tıklayarak Add –> Class diyelim ve name alanına ChangePasswordModel yazarak kaydedelim.

ChangePasswordModel.cs dosyasına çift tıklayalım ve içeriğini aşağıdaki şekilde düzenleyelim. Ben 2 den fazla parametre almasını beklediğim metotlar için küçük modeller oluşturmayı ve bu modeller vasıtası ile parametreleri almayı tercih ediyorum.

Şimdi tekrar UserController.cs dosyamızı açalım içeriğini aşağıdaki şekilde düzenleyelim.

Bir önceki derste ekleme ve çift kayıt kontrolü yaptığımız LanguageControllerı da açalım ve aşağıdaki şekilde içeriğini güncelleyelim.

Şimdi sıra geldi bir önceki derste oluşturmadığımız controllerlarımıza. Önce bu controllerlar için interfaceler oluşturacağız. Bunun için Web api projemizin altında bulunan Interfaces klasörüne aşağıdaki interfaceleri ekleyelim ve içeriklerini düzenleyelim.

IAppResourceController.cs

IOrganizationController.cs

ICustomerController.cs

Arayüzleri oluşturduktan sonra controllerları oluşturabiliriz. Bunun için web api projemizin altında bulunan Controllers klasörüne aşağıdaki controller ları ekleyelim ve içeriklerini düzenleyelim.

AppResourceController.cs

OrganizationController.cs

CustomerController.cs

Şimdi sıra geldi AutoHistory kısmına. Daha önce projemize dahil edip çeşitli ayarlar yaptığımız autohistory alt yapısının çalışması için marşa basmamız gerekiyor. Şuana kadar altyapısını kurmuş olmamız her update ve delete sonrası autohistory tablosuna kayıt atılacağı anlamına gelmiyor. Kayıtların atılması için EnsureAutoHistory komutu ile tetiklememiz gerekiyor. Bunun için ben Unitofwork sınıfımın altında bulunan savechanges metodunu kullanmayı uygun gördüm. Böylece her seferinde bu komutu vermeme gerek kalmayacak zaten veritabanında bir kaydın değişebilmesi için unitofwork sınıfımın altında bulunan savechanges metodunun tetiklenmesi gerekiyor. Ancak siz her değişikliği değiş sadece istediğiniz değişiklikleri autohistory içinde saklamak isterseniz onun için ilgili yerlerde bu komutu vermelisiniz.

Common projemize Microsoft.EntityFrameworkCore.AutoHistory isimli nuget paketini dahil edelim. Daha önceki derslerimizde nuget paketlerinin nasıl projelere eklendiğini görmüştük. Paketi projeye dahil ettikten sonra UnitofWork.cs dosyamıza çift tıklayalım ve içeriğini aşağıdaki şekilde güncelleyelim.

Sonuç

Yukarıdaki işlemleri yaptığımızda artık projemiz içinde bulunan, örnek olması amacı ile eklediğimiz tüm entitylerimiz üzerinde CRUD işlemleri gerçekleştirilebilir olacak. Lütfen postman uygulaması ile controller lar üzerinde bulunan metodları test edin, update ve delete işlemleri yaptığınızda veritabanı üzerinde bulunan AutoHistory tablosuna kayıt atılıp atılmadığını gözlemleyin. İşlemleri doğru bir şekilde yaptı isek bir update ya da delete işlemi sonrasında AutoHistory tablosunda aşağıdaki gibi bir kayıt görmemiz gerekir.

{“before”:{“CreateDate”:”2018-09-28T16:50:05.1634515Z”,”Creator”:null,”MailAdress”:”mehmetalierol@windowslive.com”,”Name”:”Mehmet Ali”,”OrganizationId”:”b57c7cab-3eeb-436c-8515-934d9c9fd055″,”PasswordHash”:null,”Phone”:”5555 444 3322″,”Status”:1,”Surname”:”EROL”},”after”:{“CreateDate”:”2018-09-28T16:50:05.1634515Z”,”Creator”:null,”MailAdress”:”mehmetalierol@windowslive.com”,”Name”:”Mehmet Ali2″,”OrganizationId”:”b57c7cab-3eeb-436c-8515-934d9c9fd055″,”PasswordHash”:null,”Phone”:”5555 444 3322″,”Status”:1,”Surname”:”EROL2″}}

Projenin buraya kadar olan kısmı ile ilgili sorun yaşıyorsanız bu link ile github üzerinden projeyi indirebilir ve kendi yazdığınız kodlar ile karşılaştırabilirsiniz. Sorularınız için yorum kısmını kullanabilir ya da mail adresim üzerinde benimle iletişime geçebilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

10- ) Web Api Projesi 1. Kısım

Business Katmanı

Projenin şuana kadar mimarisini oluşturduk, artık web api mizi yani iş katmanımızı kodlayabiliriz. İş katmanı bizim uygulamamızın ne iş yapacağını ve ne senaryolar ile çalışacağını yani işin kendisini kodladığımız yerdir. Bu katman logic ve business katmanı olarak da anılabilir.

Dependency Injection mantığını kullanabilmek adına controllerlarımızın hepsinin ne tür metotlar içereceğini yani metot imzalarını kodlayacağımız interfaceler oluşturacağız. Bunun için web api projesine solution explorer üzerinden sağ tıklayalım ve Interfaces isminde bir klasör oluşturalım. Oluşturduğumuz klasörün üzerine sağ tıklayarak Add –> NewItem diyelim dosya tipimizi Interface işaretleyelim ve Name alanına ILanguageController yazarak kaydedelim.

Controllerların Oluşturulması

Daha sonra ILanguageController.cs dosyasına çift tıklayalım ve içeriğini aşağıdaki şekilde düzenleyelim. Aşağıdaki kodu dikkatli inceleyecek olursanız IApiController Interface inden kalıtım alıyor bu nedenle ortak tüm metot imzaları zaten buraya geleceği için ekstra olarak aynı kodları tekrar yazmamıza gerek yok. Aklınıza neden o zaman bu interface’i oluşturduk sorusu gelebilir, birinci nedeni bu controller içinde farklı ve kendisine özgü metotlar yazabiliriz, ikinci neden ise dependency injection yaparken bu interface üzerinden instance alacağız.

Daha sonra Web api projemiz içerisinde bulunan Controllers sınıfına sağ tıklıyoruz ve Add –> Class diyerek Name kısmına LanguageController yazarak kaydediyoruz. Bu sınıf yukarıda oluşturduğumuz ILanguageController arayüzünden kalıtım alacak. LanguageController.cs dosyamıza çift tıklıyoruz ve içeriğini aşağıdaki şekilde düzenliyoruz.

Yukarıdaki controller içerisinde sadece CheckDublicateLanguage isminde bir metot var geri kalanlar ApiBase üzerinde kodlanmış durumda, api base generic bir sınıf olduğu için içerisine Language entitymizi, LanguageDto sınıfımızı ve Controller’ın kendisini gönderiyoruz. Eğer bu controller diğerlerinden bağımsız bir işlem yapacak ise ya da var olan ortak metotlardan (baseden gelen Add,Update,Delete,Find .. vs gibi) birini override edecek ise sınıfın içerisinde bu kodlamayı yapmamız gerekir. Farklı metotları tabiki bu kısma yazmadan önce interface içerisinde kodlamamız önemli.

LanguageController ile işlemleri bitirdiğimizde ApplicationUserController’ı oluşturacağız. Bu sınıf bizim, Identity yapısını kullanarak kullanıcı işlemleri yapmamızı sağlayacak. Kullanıcı ekleme,silme,güncelleme .. gibi ortak özelliklerin yanında bir sonraki derste göreceğimiz şifre değiştirme, mail adresi üzerinden kullanıcı bulma gibi ekstra metotları da içerecek. Öncelikle interfaceimizi oluşturacağız, bunun için web api projemize içinde bulunan Interfaces klasörüne solution explorer üzerinden sağ tıklıyoruz ve Add –> New Item diyerek, dosya tipi olarak Interface’i seçip Name alanına IUserController yazarak kaydediyoruz.

IUserController.cs dosyasına çift tıklayalım ve aşağıdaki şekilde içeriğini güncelleyelim.

Şimdi sıra UserController’ın kendisini oluşturmaya geldi bu sınıf az önce oluşturduğumuz IUserController arayüzünden kalıtım alacak. Solution explorer üzerinden wep api projemiz altında bulunan Controller klasörüne sağ tıklayalım ve Add –> Class diyerek Name alanına UserController yazıp kaydedelim. Daha sonra UserController.cs dosyasına çift tıklayarak içeriğiniz aşağıdaki şekilde düzenliyoruz.

Son olarak web api projemiz içinde bulunan startup.cs dosyasında çeşitli tanımlamalar yapacağız. Solution explorer üzerinde web api projemiz altında bulunan startup.cs dosyasını bulalım ve çift tıklayarak içini aşağıdaki şekilde güncelleyelim.

Projeyi Ateşliyoruz

Tüm işlemleri tamamladığımızda artık projeyi çalıştırıp test edebiliriz.

Klavyeden F5 tuşuna ya da debug menüsünden start debugging seçeneğine basalım. Uygulamamız çalıştığında tarayıcıda otomatik olarak açılacak ancak karşınıza tarayıcı ekranında 404 not found ibaresi gelecektir. İleriki derslerde projeye swagger kuracağız ve ilk açılışta swagger’ın gelmesini sağlayacağız. Şimdilik ilk testimizi yapmak için tarayıcıda adres satırında uygulamamızın adresinden sonra /Languages/GetAll yazalım ve entera basalım. (benim bilgisayarımda http://localhost:61025/language/getall bu link ile çalışıyor ancak sizde port farklı olabilir.) Eğer tüm işlemler doğru ise karşınıza aşağıdaki gibi bir ekran gelmeli.

Postman ile Testler

Şimdi bir de post örneği yapalım. Bunun için ben postman isimli uygulamayı kullanacağım ve anlatımı onun üzerinden yapacağım. Siz farklı bir uygulama ya da chrome üzerinden bir plug-in seçebilirsiniz, ekranlar aşağı yukarı aynı olacaktır. Postman’ı açtıktan sonra aşağıdaki ekran görüntüsünü takip edelim ve yeni bir dil eklemeyi deneyelim. Business katmanımızda yazdığımız dublicate kontrol sayesinde aynı culture değerine sahip iki farklı kayıt eklememiz engellenmiş olmalı. Deneyip sonucu görelim.

Yukarıdaki adımları tamamladığımız da ilk denememizde sonuç kısmında aşağıdaki şekilde bir görüntü görmeliyiz.

Body kısmında gönderdiğimiz Json içeriği değiştirmeden tekrar Send butonuna basarsak bu sefer aşağıdaki ekranın bizi karşılaması gerekiyor.

Aynı şekilde Yeni bir user eklemek için gereken bilgileri alt kısma yazıyorum. Postman ya da diğer rest tester uygulamaları üzerinden aşağıdaki adımları takip ederek kullanıcı eklemeyi deneyebilirsiniz. Bu işlemlerden sonra mutlaka veritabanınızı kontrol edin ve kayıtların oluşup oluşmadığınız gözlemleyin.

Kullanıcı eklemek için yapılması gerekenler;

1-) Url kısmına –>  http://localhost:61025//User/AddAsync  yazıyoruz ancak dikkat edin sizin uygulamanız farklı bir portta çalışıyor olabilir benim portum 61025.

2-) Body kısmına aşağıdaki JSON’ı yapıştırın ve içeriğini istediğiniz gibi düzenleyin. Language Id kısmına önceden eklediğiniz bir dilin Id sini yazın.

{
“emailConfirmed”: true,
“email”: “test@test.com”,
“userName”: “testuser”,
“password”: “Abc.123”,
“phoneNumber”: “112233445”,
“title”: “Manager”,
“phoneNumberConfirmed” : true,
“languageId” : “fe15e038-a5d4-450a-8c0c-b83d2f502f48”
}

Bir sonraki derste Identity alt yapısını kullanarak kullanıcı işlemlerini(sil,güncelle .. vs) tamamlayacak  ve rol işlemlerini göreceğiz.

Projenin buraya kadar olan kısmı ile ilgili sorun yaşıyorsanız bu link ile github üzerinden projeyi indirebilir ve kendi yazdığınız kodlar ile karşılaştırabilirsiniz. Sorularınız için yorum kısmını kullanabilir ya da mail adresim üzerinde benimle iletişime geçebilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

9- ) WebApi Base Sınıfı

Business kod yazma aşamasından hemen önceki adıma geldik. Bu adımı da tamamladığımızda artık projenin business katmanına yani webapi projemize geçebilir ve istemcilerin birebir iletişime geçecekleri metodlarımızı yazabiliriz. Webapi base sınıfı bizim için bütün ApiControllerın yapacakları ortak işleri tek noktaya toplamak ve tekrarlı kod yazmayı engellemek adına oluşturduğumuz bir sınıftır. Temel olarak ekleme,silme,güncelleme ve seçme işlemleri tüm controllerlarda kullanılacağı için bunları ApiBase sınıfında yöneteceğiz.

Projeden şu zamana kadar yazdığımız neredeyse tüm özellikleri bu sınıf içinde birleştireceğiz. Yavaş yavaş yazdığımız kodlar bir anlam ifade etmeye başlayacak. Sistemin mimarisi bu ders ile tamamlanıyor diyebiliriz.

Common katmanımıza giderek Api klasörünün altında bulunana Base klasörüne sağ tıklayalım ve Add –> Class diyerek Name alanına ApiBase.cs yazarak kaydedelim. Kaydettiğimiz ApiBase.cs dosyasına çift tıklayalım ve içeriğini aşağıdaki şekilde düzenliyelim.

Daha sonra ApiController larımızın interfaceleri için bir Base Interface oluşturalım. Bunun için yine Api klasörü altında bulunan Base klasörüne sağ tıklayarak Add –> Class diyoruz ve Name kısmına IApiController.cs yazarak kaydediyoruz. Daha sonra bu dosyaya çift tıklayacağız ve içeriğini aşağıdaki şekilde düzenleyeceğiz. ApiController larımızın hepsinin bir interface’i olacak ve bu interface i uygulayacaklar.

Bu şekilde işlemleri tamamladığımız da solution explorer üzerinde aşağıdaki ekran görüntüsünü alıyor olmalıyız. Kodların arasına eklediğim yorumları okumanızı tavsiye ediyorum. Bir sonraki dersimizde apicontroller larımızı oluşturarak, iş katmanımızda gerekli işlemleri kodlamaya başlayacağız.

Webapi base sınıfı ders sonrası solution explorer görüntüsü - Mehmet Ali EROL
Webapi base sınıfı ders sonrası solution explorer görüntüsü

Projenin buraya kadar olan kısmı ile ilgili sorun yaşıyorsanız bu link ile github üzerinden projeyi indirebilir ve kendi yazdığınız kodlar ile karşılaştırabilirsiniz. Sorularınız için yorum kısmını kullanabilir ya da mail adresim üzerinde benimle iletişime geçebilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

8 -) Logging ve AutoHistory

Logging ve AutoHistory

Bu yazı ile sistemimize, dosya sistemine loglama(logging on file) ve veritabanında değişikliğe uğrayan kayıtların versiyon versiyon geçmişini tutma yeteneklerini ekleyeceğiz. Loglama ve AutoHistory için ayrı nuget paketlerini projemize dahil edeceğiz. Önceki dersler işlemleri doğru yapıp yapmadığınızı kontrol etmek isterseniz bu link ile projenin son haline github üzerinden ulaşabilirsiniz.

Loglama(Logging)

Sistemimizde olup biten birtakım işlemleri saklamak, gerektiğinde kontroller yapmak ve oluşan hataları detaylıca görmek için loglama işlemleri yaparız. Loglamayı veritabanına, dosya sistemine, nosql bir veritabanına ya da bulut sistemlerine yapabiliriz. Bu örnekler arttırılabilir ancak genel olarak sıklıkla tercih edilen yöntemler bunlardır.  Bir sorunla karşılaşıldığında, şikayet alındığında ya da analiz yapılmak istendiğinde daha önceden yaratılan loglara ulaşmamız gerekebilir. Loglama stratejinizi kurguladığınız sistemin ihtiyaçlarına göre oluşturmalıyız. En önemli nokta loglama yaparken sistemin genel çalışmasının mümkün olduğunca az etkilenmesi ve performans sorunlarının ortaya çıkmamasıdır. Ben en çok tercih edilen loglama çeşitlerinin avantajları ve dezavantajlarından bahsetmeye çalıştım.

1-) Dosya Sistemine Loglama

Loglarımızı dosya sistemi üzerinde tutma işlemidir. Sistemden üretilen tüm loglar belirlenen formatta dosya sistemi üzerinde barındırılır. Dosya üzerine loglama işlemlerinde en önemli noktalardan bir tanesi log dosyasının boyut kontrolüdür. Eğer dosya boyutu kontrolsüz bir şekilde büyüyecek olursa, uygulamamız artık o dosya üzerine log yazmaya çalışırken oldukça fazla zaman harcayacak, belkide hiç loglama yapamayacak hale gelecektir. Bu duruma genelde log dosyasının şişmesi denir. Loglamayı sağlıklı yapamadığımız için sistemin diğer işlevlerinde sorunlar çıkabilir, çok basit işlemler uzun vakitler alabilir ve uygulamamızın geneli bu sorun nedeni ile işlevini yitirebilir. Dosya boyutu mutlaka kontrol edilmeli ve belirlenecek stratejiye göre belli bir boyutun üstüne çıktığında hemen yeni bir log dosyası açarak performans sorunlarının önüne geçilmelidir. Mümkün ise bu logları bir file server üzerine yazmalı ya da en azından farklı bir diske kaydetmemiz daha sağlıklı olacaktır.

Gereksiz loglamadan kaçınmalı ve ihtiyacımız olanı loglayacak şekilde planlama yapmalıyız.  Dosya sistemine aldığımız logların başkası tarafından silinmemesi için gerekli önlemleri almalıyız. Log dosyalarının boyutu sistemin diskini doldurmadan başka bir yere taşımalı ya da ilk yazılan logların otomatik olarak silinmesini sağlayacak şekilde kurallar oluşturmalıyız. Dosya sistemine yazdığımız logları belli bir ayırıcı ile ayırmalı ve programatik olarak okunabilecek seviyede bir veri seti olarak saklamalıyız. Bu logların okunması ve analiz edilmesi, veri tabanına (uygulamanın kendi veritabanı ya da elastiksearch ile nosql çözümleri gibi) yazılan logların analiz edilmesinden daha zor olacaktır ve daha fazla vakit gerektirecektir.

2-) Uygulamanın Veritabanın Loglama

Uygulamanın kendi veritabanına loglama yapma işlemi oldukça kritik işlemler ve kayıtlar için mantıklı olabilir ancak her türlü logun veri tabanına yazılması performans sorunlarına yol açabilir. Mssql veritabanı üzerinden konuşacak olursak, oluşturulan her bir işlemin(transaction) log kaydı veritabanımıza ait log dosyası üzerine yazılmaktadır. Eğer her türlü logu veritabanı yazacak olursak bu bizim için bir transaction olacak ve bizim loglarımız için mssql de log yazma işlemi gerçekleştirecek. Transaction loglar veritabanı için oldukça önemlidir, sistemde yaşanacak sorunlar yanlış yapılan işlemler gibi felaket durumlarında kurtarıcı olabilirler. Yukarıda anlattığım durumda biz bir log işlemi için sisteme iki adet log yazmış olacağız ki bu durumda bizim için maliyet anlamına geliyor. Log şişmesi durumu iyi kontrol edilmeyen ve profesyonel olarak yönetilmeyen veri tabanlarında sıklıkla karşılaşılabilecek bir durumdur. Bu durum ortaya çıktığında veri tabanında uygulamanın da performans sorunları baş gösterecektir.

Veritabanına loglama yapmak geriye dönük aramalarda ve analizlerde oldukça hız kazandıracaktır ancak her türlü loglamanın veritabanına yapılması ciddi bir veri tabanı yönetimi ve senaryolara göre ek maliyetler gerektirecektir.

3-) NoSQL Veritabanlarına Loglama(Elasticsearch)

Bu seçenek son zamanlarda gittikçe popülerleşen bir yaklaşım. Verilerinizi kibana gibi open source elastic search alt yapısına sahip sistemlerde saklayabilir ve MongoDB, Cassandra, CouchDB gibi nosql veritabanları kullanırlar. Başka derslerde bu veritabanlarının çalışma prensiplerinden, artı ve eksi yönlerinden bahsedeceğiz. Şimdilik ilişkisel olmaya şekilde verilerin tutulduğu ve yatay olarak genişleyebilen yapılar olduklarını bilsek yeterli. Bu şekilde loglama yapmak bize analiz ve geriye dönük aramalarda hız kazandıracaktır. Elasticsearch alt yapısı ile saklanan veriler kelime kelime indexlenerek saklanır ve büyük veriler içerisinde arama yapmak oldukça performanslı bir hale gelir.  Ancak bu şekilde bir alt yapı kurmak ve yönetmek ayrı bir maliyettir. Kuracağınız sistemler opensource olduğu için en azından bu sistemlerde oluşabilecek sorunlara müdehale edecek kadar bilgi sahibi olmanız ya da dış destek almanız gerekebilir.

Hangi Yönetimi Kullanmalıyım?

Yukarıda açıklamaya çalıştığım yöntemler dışında, bulut sistemlerine log yazmak, mail ile logları saklamak hatta kullanıcının bilgisayarında log saklamak bile bir yöntemdir ve yerine göre bu yöntemler işimize yarıyabilir. Hangi yönetimi kullanacağımıza, oluşturduğumuz sistemin geneline ve ihtiyaçlarına bakarak(yazılım alanının neredeyse her karşılaştırmasında olduğu gibi) karar vermeliyiz. Az kullanıcılı ve transaction sayısı az olan bir uygulamamız var ise veritabanına loglama yapmak daha akıllıca olabilir ancak işler biraz daha büyüdüğünde hayati loglamaları veritabanına geri kalanları dosya sistemine yapma seçeneğini kullanabiliriz ve artık log dosyalarımız big data seviyelerine gelmeye başladıysa ve geriye dönük olarak tümüne ihtiyacımız varsa elasticsearch yapısından yararlanmak kuvvetli bir seçenek haline gelebilir.

Geliştireceğimiz uygulamanın ne kadar uzun ömürlü olacağı ve kalite algısı bu tarz stratejik kararlara bağlıdır. Geliştirdiğiniz uygulamadan gururla bahsetmek yerine kötü stratejiler yüzünden uygulamanızdan nefret edebilirsiniz. Bir uygulama geliştirirken, desteği, bakımı ve sonradan eklenmesi olası özellikleri düşünerek stratejiler belirlemeli ve planlama aşamasında diğer tüm aşamalardan çok vakit harcamalıyız. Loglama diyerek bu konuyu küçümsemek çok büyük problemlere yol açabilir ve hatta uygulamanızın çalışmasını engelleyebilir.

Uygulamamızın Loglama Altyapısı

Biz uygulamamızda iki farklı seçenek kullanacağız. Stratejimizi veriler ve veriler üzerinde yapılan işlemlere göre iki ana başlıkta belirleyeceğiz. Veriler ile ilgili güncelleme,silme gibi değişiklikleri veri tabanında tutarken, istemcinin api ile haberleşmesi, sistem hata logları ve diğer custom logları dosya sisteminde saklayacağız. Veritabanına loglama için AutoHistory nuget paketini, dosya sistemine loglama için NetEscapades.Extensions.Logging nuget paketini kullanacağız.

.Net Core ile Dosyaya Loglama İşlemleri

Projenin başlangıcında kullandığım dosyaya loglama alt yapısı yerine kullanımı daha kolay olan farklı bir paket keşfettim, bu nedenle Common katmanımız içerisinde bulunan Logging klasörüne ihtiyacımız kalmadı. O klasörü projeden kaldırabiliriz. Daha sonra Solution Explorer üzerinden web api projemize sağ tıklıyoruz ve Manage Nuget Packages diyerek Nuget paket yöneticisini açıyoruz.

Loglama için gerekli nuget paketi yükleme ekranı - Mehmet Ali EROL
Loglama için gerekli nuget paketi yükleme ekranı

Daha sonra aşağıdaki adımları takip ederek ilgili paketi WebApi projemize dahil ediyoruz.

Loglama için gerekli nuget paketi yükleme ekranı 2 - Mehmet Ali EROL
Loglama için gerekli nuget paketi yükleme ekranı 2

Paketi ekledikten sonra projemize bir appsettings.json dosyası ekleyeceğiz. Bu dosyanın içinde loglama ile ilgili ayarları saklayacağız. Bunun için aşağıdaki ekran görüntülerini takip ederek gerekli işlemleri yapalım.

appsettings.json dosyasının projeye eklenmesi - Mehmet Ali EROL
appsettings.json dosyasının projeye eklenmesi
appsettings.json dosyasının projeye eklenmesi 2 - Mehmet Ali EROL
appsettings.json dosyasının projeye eklenmesi 2

WebApi projemize eklediğimiz appsettings.json dosyasına çift tıklayalım ve içeriğini aşağıdaki şekilde düzenleyelim. FileSizeLimit içinde yazan değer 20 megabyte ın byte değeridir ve 20 * 1024 * 1024 şeklinde hesaplanabilir.

WebApi projesi içinde bulunan Startup.cs dosyasına çift tıklayarak aşağıdaki şekilde düzenlemeler yapalım.

Başlangıç projesini WebApi yapmak için Solution Explorer üzerinden WebApi projemize sağ tıklayalım ve Set as Startup Project diyelim. Daha sonra klavyeden F5 tuşuna basabilir ya da Debug menüsünden Start Debugging diyerek projeyi çalıştırabilirsiniz. Proje çalıştığında output tabında çeşitli mesajlar görünecektir. Projeyi durdurarak appsettings.json dosyası içinde Logging segmentinin içinde bulunan “Microsoft”: “Warning” değerini “Microsoft”: “Information” olarak değiştirelim ve tekrar projeyi çalıştıralım. İki şekilde de output tabında görünen değerleri inceleyelim. Information yazdığımızda microsoft ismi ile gelen logların arttığını görebilirsiniz. Daha sonra Solution Explorer kısmına baktığınızda LogFiles klasörünün oluşturulduğunu ve içine bir adet log dosyası yazıldığını görmemiz gerekiyor. Bu dosyanın adı bizim belirttiğimiz gibi applicationLog- ile başlıyor ve bugünün tarihini ile sonlanıyor. Belirttiğimiz sınıra geldiğinde ise aynı isimle yeni bir dosya açılacak ve loglama o dosya üzerinden devam edecek.

Dosyaya loglama alt yapısını oluşturduk ve test ettik. Projenin ilerleyen bölümlerinde custom olarak nasıl log yazacağımızı göreceğiz.

Auto History

Entitylerimiz üzerinde değişiklikler olduğunda bunların loglanması ve geçmişe dönük analiz edilerek gerektiği durumlarda kanıt ya da yol gösterici olarak çekilmesi önemlidir. Bu işlemi kaydın versiyonlarını tutmak da diyebiliriz. İlgili kaydın ilk eklenme zamanından son haline kadar geçirdiği değişimleri saklamak oldukça önemli bir konudur. Özellikle kurumsal projelerde bu kayıt neden değişti ya da bu zamana kadar bu kayıt üzerinde ne değişiklikler yapıldı gibi sorulara cevap vermek hayati önem taşır.

Peki biz bu değişimleri neden dosya sistemine loglamıyoruz? Aslında istersek dosya sisteminde de saklayabiliriz ancak geriye dönük arama yapmak analizlerde kullanmak biraz daha zahmetli bir hal almaya başlayacaktır. Bu loglar ile diğer loglar karışabilir ve aradığımızı bulamaz noktaya gelebiliriz. Bu nedenle bu projede kayıt değişikliklerini AutoHistory ile veri tabanında bir tabloda tutacağız.

İlk olarak Solution Explorer’dan en üstte bulunan Solution adına (Company.Application) sağ tıklayarak nuget paket yöneticisini açıyoruz ve aşağıdaki paketi seçerek Data projesine dahil ediyoruz.

AutoHistory nuget paketinin projeye dahil edilmesi - Mehmet Ali EROL
AutoHistory nuget paketinin projeye dahil edilmesi
AutoHistory nuget paketinin projeye dahil edilmesi 2 - Mehmet Ali EROL
AutoHistory nuget paketinin projeye dahil edilmesi 2

Son olarak Data projemiz altında bulunan Context klasöründeki ApplicationDbContext.cs dosyasına çift tıklıyoruz ve içeriğini aşağıdaki şekilde düzenliyoruz.

Sonuç

Bu ders ile projemize dosyaya loglama ve veritabanına loglama yeteneklerini eklemiş olduk. Buraya kadar yaptığımız işlemleri kontrol etmek isterseniz bu link ile github üzerinden projeye ulaşabilirsiniz. Bu kısım için yaşadığınız bir sorun ya da sormak istediğiniz bir soru varsa yorum kısmında ya da mail adresim üzerinden iletebilirsiniz.
Mail adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

7-) Paging Altyapısı

Paging Nedir ve Neden Kullanılır?

Web apimizi kullanacak istemciler için database üzerinde bulunan kayıtların listesini döneceğimiz metot ya da metotlarımız olacak. Bu metotları kontrol ederek kısıtlamaz isek bağlanan istemci veritabanında bulunan yüksek miktarda veriyi gereksiz yere tek seferde çekmeye çalışabilir. 5000 kayıt barındıran bir müşteri tablomuz olduğunu varsayalım ve bu müşterileri frontend tarafında ekranda listelemeye ihtiyacımız olsun. Kullanıcı bu sayfaya her girdiğinde backend den sürekli olarak 5000 kayıt mı isteyeceğiz? Birde bu uygulamayı yüzlerce kişinin kullandığını düşünecek olursak ortaya ciddi bir alt yapı maliyeti çıkacaktır. Oysaki biz bu 5000 kaydın her seferinde sadece 50 tanesini göstersek ve bir paging alt yapısı kursak, her seferin bir kullanıcı en fazla 50 kayıt görüntüleyebilir ve diğer kayıtları görmek için paging linklerinden faydalanabilir.

Ne elde etmiş olduk?

Bu sayede backend tarafında gereksiz yere kaynak kullanımının önüne geçmiş oluruz. Sadece sunucu tarafında değil aynı zamanda sunucu ve istemci arasında oluşacak trafik üzerinde de ciddi anlamda iyileştirme yapmış oluruz. Common projemizin içinde bulunan paging klasörüne aşağıdaki dosyaları oluşturalım. Paging klasörüne sağ tıklayarak Add –> Class diyoruz ve oluşturacağımız sınıfın adına PagingParams yazarak ekliyoruz. Eklediğimiz PagingParams.cs dosyasına çift tıklayarak aşağıdaki şekilde içeriğini değiştiriyoruz.

Daha sonra paging modeli ile birlikte göndereceğimiz linklerin modelini oluşturuyoruz. Bunun için Paging klasörüne sağ tıklayarak Add –> Class diyeceğiz ve LinkInfo ismi ile kaydedeceğiz. Daha sonra LinkInfo.cs dosyasına sağ tıklayarak aşağıdaki şekilde içeriğini değiştireceğiz.

Sayfalanmış bir model geriye dönerken bu modele bir header bölümü ekleyeceğiz. Bu header kısmında kaç adet muhtemel sayfa olduğu, şuan kaçıncı sayfanın frontend e gönderildiği, gönderilen sayfada kaç satır bilgi olduğu ve toplam tüm sayfaların satır sayılarının toplamı gibi bilgiler vereceğiz. Bunun için Paging klasörüne PagingHeader isminde bir sınıf oluşturacağız. Oluşturduğumuz PagingHeader.cs dosyasına çift tıklayarak içeriğini aşağıdaki şekilde düzenleyelim.

Sayfalama yapılmış bir liste oluşturmak için biraz önce oluşturduğumuz PagingHeader sınıfınıda içerecek bir sınıf oluşturacağız. Bu sınıf bizim için sayfalanmış bir sonuç ve bu sonuca dair header bilgilerini tutacak. Paging klasörüne sağ tıklıyoruz Add –> Class diyerek Name alanına PagedList yazıyoruz ve kaydediyoruz. Daha sonra eklediğimiz PagedList.cs dosyasına çift tıklayarak içeriğini aşağıdaki şekilde düzenliyoruz. 

Yukarıda kodladığımız paging yapısını birleştirecek ve geri dönüş için kullanılacak bir sınıf oluşturacağız. Bu sınıfa OutputModel ismini vereceğiz. Tüm sayfalama işlemleri tamamlandığında bu sınıf içinde son halini alacak ve istemciye gönderilecek. Bunun için Paging klasörüne sağ tıklıyoruz Add –> Class diyoruz ve Name alanına OutputModel yazarak kaydediyoruz. Daha sonra OutputModel.cs dosyasına çift tıklayarak içeriğini alağıdaki şekilde değiştiriyoruz.

Paging klasörünün altına Interfaces isminde bir klasör açıyoruz, bu klasör bizim için interfaceleri barındıracak. Sonra bu Interfaces klasörü içerisine IPagingLinks isminde bir interface oluşturuyoruz. Oluşturduğumuz IPagingLinks.cs dosyasına çift tıklayalım ve aşağıdaki şekilde içeriğini düzenleyelim.

Son olarak linkleri oluşturacak ve IPagingLinks arayüzünü implemente edecek sınıfımızı oluşturuyoruz. Öncesinde IPagingLinks arayüzünü oluşturma sebebimiz dependency injection kullanabilmek.

Interface’ler ve Dependency Injection

Uygulamamızın mümkün olduğunca doğrudan bağımlılıklara sahip olmasını engellememiz gerekiyor. Dependency injection ile bu bağımlılıkları arayüzler vasıtası ile enjekte ediyoruz. Örnek verecek olursan bu sınıfın yaptığı işi daha farklı şekilde yapan başka bir sınıfımız olabilir ve biz bu backend projeyi A müşterisinde mevcutta yazdığımız şekilde B müşterisinde başka bir sınıfla yapmak mecburiyetinde kalabiliriz. Bu durumda eğer arayüzler ile çalışarak dependency injection kullanıyor isek yapmamız gereken tek şey o arayüzü implemente eden iki farklı sınıf yazmak ve ileride göreceğimiz startup.cs dosyası içerisinde deploy aşamasında hangi sınıfın bu arayüz ile eşleştirileceğini belirtmek olacak. Paging klasörüne sağ tıklayalım Add –> Class diyerek Name alanına PagingLinks yazarak kaydedelim. Daha sonra bu dosyaya çift tıklayarak içeriğini aşağıdaki şekilde güncelliyoruz. 

Sonuç

Bu son işlemi de yaptığımızda artık paging alt yapımız hazır hale gelmiş oluyor. Eğer işlem adımlarını doğru uyguladıysak Solution Explorer üzerinde aşağıdaki ekran görüntüsündeki gibi bir yapı görüyor olmalıyız.

Paging nedir, paging yapısı
Paging işlemlerinin doğru yapılması sonucunda görülmesi gereken sonuç.

Common projemiz için tek eksik kalan nokta AutoHistory ve logging alt yapısı. Sonraki derste bu özellikleri projemize dahil edeceğiz.  Buraya kadar olan kısmı kontrol etmek için projenin son haline github sayfamdan bu link ile ulaşabilirsiniz. Benimle iletişime geçmek için yorum kısmını kullanabilir ya da mail atabilirsiniz. 
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

6-) Generic Repository ve UnitofWork

Başlarken

Önceki derslerde projemizde code first ile veritabanı tasarımı yapmıştık. Peki bu tablolar üzerinde CRUD(Create, Read, Update, Delete) işlemlerini nasıl yapacağız? Eğer klasik yöntemleri kullanacak olsaydık yüksek ihtimal ile her bir entity için ayrı ayrı yönetim sınıfları oluşturacak ve aynı kodları tekrar tekrar yazacaktık. Bu dersimizde Generic Repository ve UnitofWork desenlerini projemize dahil edeceğiz.

Generic Repository ve Unitofwork

Yazılım geliştirmede en önemli konulardan bir tanesi ortak noktaları görmek ve tekrarlı kod yazmaya yönelten tasarımlardan uzak durmaktır. Tüm entity lerimizde yapacağımız işlemler temelde aynı. Hepsinde ekleme, silme, seçme, güncelleme işlemleri yapacağız. Tabiki her entity’nin business ile ilgili ekstra kodları olacaktır ancak o kodlar o entitye özel olacağı için tekrarlı kod yazmak anlamına gelmeyecek sadece bir kez yazılacaklardır.  Repository pattern ile bu ortak işlemleri generic bir sınıf oluşturarak tek bir noktadan yürütebiliriz. Üzerinde CRUD işlemler yapmak istediğimiz entity sınıfımızı generic type olarak Repositorye gönderdiğimizde geri sadece yapmak istediğimiz işin komutunu vermek kalacak. Biz bu uygulamamızda Generic Repository ve UnitofWork alt yapısını kullanacağız. Repository bizim için yapılacak işleri bir kuyruğa ekleyecek ve zamanı geldiğinde unitofwork bu kuyrukta bulunan işlerin veritabanında gerçekleşmesini sağlayacak. Unitofwork genellikle sıralı işlere sahip uygulamaların alt yapısında kullanılmaktadır.

Günlük hayattan bir örnek vermeye çalışırsak bir oto kuaförümüz olduğunu varsayalım, işletmemizin cilalama, iç yıkama ve dış yıkama hizmetleri olsun. Her bir hizmeti yapmak için ayrı bölmelerimiz olduğunu varsayalım(İç yıkama alanı, dış yıkama alanı, cilalama alanı). Ödemeyi almadan da hizmet vermiyoruz. Müşteriler araçları getirdiğinde onları bizim Repository Ahmet karşılayacak  ve araca ne işlem yapılması gerektiğini öğrenerek ilgili hizmetin bölmesinde aracı sıraya sokacak(A aracına iç yıkama, B aracına cilalama .. vs). Burada dikkat etmemiz gereken husus araçlara henüz işlem yapılmadı ama işlem yapılmak üzere etiketlendi ve kuyruğa eklendi. Bu arada unitofwork Hasan ödemesi yapılan yani SaveChanges işlemini yapmış müşterilerin araçlarını gerekli işlemleri yapmak üzere ilgili bölümlere yönlendirecek ve artık fiziki olarak hizmet tamamlanmış olacak. Böylece bu işlemleri izole ettik ve birbirinden ayırdık. Herkes kendi işini yapıyor ve yönetilmesi daha kolay bir yapı ortaya çıkıyor. Zorlarsak kabaca bu şekilde bir yapı var diyebiliriz. :)

IGenericRepository Arayüzü

Şimdi Repository için önce bir Interface oluşturacağız ve repository içinde yapılmasını istediğimiz işlemlere ait metotların imzalarını tanımlayacağız. Interfacelerde metotların body’leri olmaz sadece ve sadece imzaları dediğimiz kısım yani ne parametre aldıkları ve ne cevap döndükleri bilgisi bulunur. Interface oluşturmak için aşağıdaki ekran görüntüsünü takip edebilirsiniz.

Generic Repository Interface'inin eklenmesi - Mehmet Ali EROL
Generic Repository Interface’inin eklenmesi

Common projemiz içerisinde bulunan Repository klasörüne sağ tıklayarak “Add –> Class” diyoruz.

Generic Repository Interface'inin eklenmesi 2 - Mehmet Ali EROL
Generic Repository Interface’inin eklenmesi

Açılan ekranda nesne tipi olarak interface seçiyoruz ve Name alanına IGenericRepository yazarak kaydediyoruz.

Eklediğimiz IGenericRepositoru interface’ine çift tıklayarak dosyayı açıyoruz ve içeriğini aşağıdaki şekilde düzenliyoruz.

GenericRepository Sınıfı

Artık projemizde kullanacağımız Repository nin hangi metotları içermesi gerektiğini biliyoruz. Sıra GenericRepository sınıfımızı oluşturmaya geldi.

Generic Repository sınıfının eklenmesi - Mehmet Ali EROL
Generic Repository sınıfının eklenmesi

Repository klasörüne sağ tıklayarak tekrar “Add –> Class” diyoruz.

Generic Repository sınıfının eklenmesi 2 - Mehmet Ali EROL
Generic Repository sınıfının eklenmesi 2

Daha sonra açılan ekrandan nesne tipini class olarak seçiyoruz ve Name alanına GenericRepository yazarak kaydediyoruz.

Oluşturduğumuz GenericRepository.cs dosyasına çift tıklıyoruz ve içeriğini aşağıdaki şekilde düzenliyoruz.

IUnitofWork Arayüzü

Repositoryden sonra sırada UnitofWork sınıfı var, bu sınıfı oluşturmak için yine bir interface ekleyerek metot imzalarımızı yazacak ve bir unitofwork sınıfında neler bulunması gerektiğini belirteceğiz. Bu kez Common projemiz altında bulunan UnitofWork klasörüne sağ tıklıyoruz ve “Add –> Class” dedikten sonra nesne tipi kısmından interface’i seçip Name alanına IUnitofWork yazarak kaydediyoruz.

Oluşturduğumuz IUnitofWork.cs dosyasına çift tıklayarak içeriğini aşağıdaki gibi düzenliyoruz.

UnitofWork Sınıfı

Son olarak UnitofWork sınıfımızı oluşturacağız, bunun için UnitofWork klasörüne sağ tıklayarak “Add –> Class” diyoruz ve Name alanına UnitofWork yazarak kaydediyoruz.

Unitofwork.cs dosyasına çift tıklayarak içeriğini aşağıdaki gibi düzenliyoruz.

Generic Repository ve Unitofwork dersi sonucunda SolutionExplorer görüntüsü - Mehmet Ali EROL
Generic Repository ve Unitofwork dersi sonucunda SolutionExplorer görüntüsü

Buraya kadar yaptığımız işlemleri doğru yaptı iseniz Solution Explorer üzerinde aşağıdaki gibi bir görüntü görüyor olmanız gerekiyor.

Kontrol etmek isterseniz projenin son haline github sayfam üzerinden bu link ile ulaşabilirsiniz. Sormak istediğini herhangi bir soru var ise yorumlar kısmından ya da mail adresim üzerinden bana ulaşabilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

5-) Dto Katmanı ve AutoMapper

Dto Katmanı

Bu derste entitylerimiz ile veritabanından aldığımız verileri aktaracağımız ve ekleme,silme,güncelleme işlemleri öncesi verileri tutacağımız “Dto” katmanımızı oluşturacağız ve AutoMapper ‘ı projemize dahil edeceğiz. “Data transfer object” ler içlerinde business kod bulundurmazlar görevleri sadece verileri taşımak ve geçici olarak saklamaktır. Şimdi “Solution Explorer” içinden “Dto” projemize sağ tıklayalım “Add –> Class” diyerek yeni bir sınıf oluşturalım ve “OrganizationDto” olarak isimlendirelim. Artık yeni dosya oluşturma ekranlarını eklemeye gerek görmüyorum ancak bu konuda takıldığınız bir durum olur ise önceki derslere dönerek ekran görüntülerine bakabilirsiniz.

Dto Sınıflarının Oluşturulması

“Common” projesini oluştururken hazırladığımız “DtoBase” sınıfı oluşturduğumuz tüm “Dto” sınıfları için “base class” görevi görecek yani tüm “Dto” larımız bu sınıftan kalıtım alacak. “DtoBase” sınıfı “Common” projesi altında bulunduğu için “Dto” projemize sağ tıklayarak “Add –> Reference” diyoruz ve açılan pencereden “Common” projesini seçerek ekliyoruz. “OrganizationDto.cs” dosyasına çift tıklayarak içini aşağıdaki şekilde değiştiriyoruz.

Sırası ile aynı yönetmi uygulayarak “CustomerDto, LanguageDto, AppResourceDto, ApplicationRoleDto, ApplicationUserDto, ApplicationUserRoleDto” sınıflarınıda Dto projesine ekleyelim ve içeriklerini aşağıdaki gibi güncelleyelim.

CustomerDto.cs

LanguageDto.cs

AppResourceDto.cs

ApplicationRoleDto.cs

ApplicationUserDto.cs

ApplicationUserRoleDto.cs

AutoMapper

Dto ları ekledikten sonra sıra geldi AutoMapper alt yapısını oluşturmaya. Data katmanında eklediğimiz entityler daha öncede bahsettiğimiz gibi üzerlerinde CRUD işlemler yapmak için oluşturuldu. Görevleri sadece veritabanımızda bulunan tablolarımızı temsil etmek, yani son ana kadar bu sınıflara erişmek istemiyoruz, doğrudan bu katmana bir manipülasyon olmasını tercih etmiyoruz, araya Dto katmanını ekleyerek uygulama içerisinde aksiyon anına gelene kadar (Database gönderilecek CRUD komutları) verileri bu katman üzerinde tutacağız. Bu katmandaki sınıflar olabildiğince basit ve hiç bir şekilde business içermiyor. Peki her seferinde Dto to Entity ya da tam tersi Entity to Dto arasında veri akışını manuel mi kodlayacağız? Eğer hayatımızda AutoMapper çözümleri olmasaydı maalesef her bir sınıf içerisinde tekrar tekrar bu transferleri kodlayacaktık. Birde herhangi bir entitynin değiştiğini düşündüğünüzde bu durum kod yönetimini ve test odaklı yazılım geliştirme döngüsünün olmazsa olmaz refactoring aşamasını olumsuz etkileyecek bir hal alacaktı.

AutoMapper Nasıl Çalışır?

Kodların içerisinde bulunan yorumlarda da yazdığım gibi eğer entity ve dto sınıflarımızın property isimleri ve valueType ları aynı olur ise AutoMapper bu properylerin birbirine eşit olduğunu anlıyor ve hemen iki property arasında kaynak(source) –> hedef(target) ilişkisine göre veri transferi gerçekleştiriyor. Peki property isimleri aynı olmazsa ne oluyor? Burada da devreye AutoMapper’ın profile sınıfı altında bulunan genişletme kodları giriyor. Hedef ve kaynak arasında birbirine eşit propertyleri tek tek tanımlayarak bir mapping oluşturmuş oluyorsunuz ve isimleri aynı olmasa dahi bu iki propertyi maplediğiniz için veri transferi gerçekleşiyor. Herhangi bir property nin aktarılmasını istemiyorsanız ya da aktarılması esnasında değer içinde değişiklik yapmak istiyorsanız yine profile sınıfı içinde genişleme kodları ile bu işlemleri yapabilirsiniz.

AutoMapper Projeye Nasıl Eklenir?

Şimdi AutoMapper’ı projemize eklemek için aşağıdaki ekran görüntüsünde olduğu gibi Dto projemize sağ tıklayacağız ve Manage Nuget Packages diyerek nuget paket yöneticisini açacağız.

AutoMapper paketinin projeye eklenmesi - Mehmet Ali EROL
AutoMapper paketinin projeye eklenmesi

Daha sonra karşımıza gelen ekranda aşağıdaki adımları takip ederek projemize AutoMapper paketini dahil edeceğiz.

AutoMapper paketinin projeye eklenmesi 2 - Mehmet Ali EROL
AutoMapper paketinin projeye eklenmesi 2

AutoMapper Profile ile Mapleme

Bu işlemleri doğru bir şekilde yaptığımızda artık projemize AutoMapper’ı dahil ettik ve bu paketin altında bulunana Profile sınıfını kalıtım alan bir MappingProfile oluşturabiliriz.
Bunun için Dto projesine bir klasör ekliyoruz ve adına Mapper diyoruz (Bu klasörü oluşturmak zorunlu değil ben diğer sınıflardan ayrı bir yerde durmasını istediğim için bu klasörü açtım). Daha sonra bu klasöre sağ tıklayarak “Add –> Class” diyoruz ve oluşturacağımız sınıfın adına MappingProfile yazarak kaydediyoruz. Mapping yapabilmek için Dto projesine Data projesini referans vermeliyiz. Hemen Dto projesine sağ tıklayarak “Add –> Reference” diyoruz ve açılan pencereden Data projesini işaretleyerek kaydediyoruz. Son durumda Dto projemiz hem Common hem de Data projelerine bağımlı hale geldi.

MappingProfile.cs dosyasına çift tıklayarak içerisini aşağıdaki şekilde güncelliyoruz.

Sonuç

Dto ve AutoMapper işlemleri sonrası Solution Explorer Görüntüsü - Mehmet Ali EROL
Dto ve AutoMapper işlemleri sonrası Solution Explorer Görüntüsü

Bu işlemleri yaptığımızda artık Dto katmanımız ve AutoMapper alt yapımız hazır hale geliyor. İşlemleri doğru bir şekilde yaptı ise Solution Explorer üzerinde aşağıdaki gibi bir görüntü görüyor olmalıyız.

Projenin son haline github sayfam üzerinden bu link ile erişebilir ve buraya kadar yaptığımız işlemleri kontrol edebilirsiniz.

<- Önceki Post – Sonraki Post ->