ASP.NET Boilerplate: Modern Bir Web Uygulama Kütüphanesi
Yazılımcılar olarak birbirinden çok farklı iş kollarına hitap eden farklı uygulamalar geliştiriyoruz. Ancak hepimiz belli bir seviyede de olsa temel ve ortak yapıları tekrar tekrar uygulamak durumunda kalıyoruz. Örneğin çoğu projede Authorization veya Logging gibi katmanlar yazmışızdır, hatta birçok projede bu katmanların hemen hemen aynı yapıda olduğunu da görmüşüzdür. Projelerimizde Authorization, Validation, Exception Handling, Logging, Localization, Database Connection Management, Setting Management, Audit Logging bunlardan bazıları. Ayrıca Katmanlı ve Modüler Mimari, Domain Driven Design, Dependency Injection gibi katmanları best practice diyebileceğimiz mimari yapılar üzerine kuruyoruz, uygulamamız içerisindeki kodların belli bir mimariye göre benzer/ortak yapıda geliştirilmesi için çabalıyoruz.
Bütün bunlar oldukça zahmetli işler olduğu için birçok şirket kendi içerisinde framework’ler hazırlıyor, projelerinde bu framework’leri kullanarak asıl uygulamalarını çok daha kolay, hızlı ve hatasız geliştirmenin yollarını arıyor. Tabii her şirketin bu şekilde bir framework hazırlayacak ekibi, zamanı ve bütçesi olmayabiliyor.
ASP.NET Boilerplate, “her şirket tek tek uğraşmasın, tüm .NET developer’lar için ortak bir framework geliştirelim” hedefiyle ortaya çıkmış açık kaynak kodlu, iyi dokümante edilmiş bir projedir. Sadece framework değil, modern uygulamalar için DDD(Domain Driven Design) tekniklerini baz alan sağlam bir mimari ve model sunar.
Hızlı bir örnek
ASP.NET Boilerplate’in geliştireceğimiz uygulamalarda ne gibi bir fayda sağladığını görmek için aşağıdaki basit sınıfı inceleyelim:
public class TaskAppService : ApplicationService, ITaskAppService { private readonly IRepository _taskRepository; public TaskAppService(IRepository taskRepository) { _taskRepository = taskRepository; } [AbpAuthorize(MyPermissions.UpdatingTasks)] public async Task UpdateTask(UpdateTaskInput input) { Logger.Info("Updating a task for input: " + input); var task = await _taskRepository.FirstOrDefaultAsync(input.TaskId); if (task == null) { throw new UserFriendlyException(L("CouldNotFoundTheTask")); } input.MapTo(task); } }
Burada bir Application Service metodu görüyoruz. DDD(Domain Driven Design)’de Application Service’ler önyüzden direkt olarak kullanılan/çağırılan sınıflardır. UpdateTask metodunun AJAX ile çağırıldığını düşünebilirsiniz. Burada ASP.NET Boilerplate’in (kısaca ABP) bize ne sağladığına bakalım:
- Dependency Injection: Bu (base class’dan dolayı) bir application service olduğu için Transient olarak Dependency Injection sistemine otomatik olarak kaydedilmiştir. Kendisi için gereken tüm servisleri (bu örnekte sadece bir Repository) direkt olarak inject edebilir (constructor ya da property injection yapılabilir). ABP conventional, kolay kullanımlı ve hazır bir DI altyapısı sağlar.
- Repository: Her Entity için otomatik olarak bir repository oluşturulur. IRepository<Task> şeklinde Task repository’sini kullanıyoruz burada. IRepository’nin birçok hazır metodu var. FirstOrDefault bunlardan birisi.
- Authorization: Eğer bu servisi çağıran kullanıcının “task güncelleme” yetkisi yoksa daha metod çağrısı başlamadan uygun bir authorization exception fırlatır. Attribute kullanarak authorization kontrolünü basitleştirmiş oluyoruz.
- Validation: UpdateTaskInput DTO’su (Data Transfer Object) içerisinde Task Entity’siyle isim ve tip olarak birebir eşleşen property’ler var. Normalde ilk iş bunların validate edilmesi gerekiyor. ABP data annotation’lar ve custom validation teknikleri kullanarak gelen input’un property’lerini otomatik olarak validate eder, eğer valid değilse client’ın anlayacağı formatta bir Exception fırlatır (AJAX çağrısı için uygun bir JSON döner örneğin). Ayrıca nesnenin kendisinin null olmasına da izin vermez, böylece input == null mı kontrolüne gerek kalmaz.
- Audit Logging: Eğer audit logging açıksa bu metod çağrısını yapan kullanıcı, çağrının yapıldığı zaman, IP… gibi bilgilerle beraber çağrılan metod ve parametrelerini kaydeder. Ayrıca süre ölçümü de yapar, böylece yavaş metodlarımızı tespit edip kontrol edebiliriz.
- Unit Of Work: Her application service metodu bir unit of work kabul edilir. ABP, metoda girerken veritabanı bağlantısını otomatik olarak açıp bir transaction başlatır. Eğer metod hiçbir Exception fırlatmadan başarıyla tamamlandıysa transaction otomatik olarak commit edilerek bağlantı kapatılır. Böylece metod içerisinde farklı repository’leri dahi kullansak tüm işlemler atomic olmuş olur. Ayrıca Entity’lerde yapılan tüm değişiklikler eğer hata olmazsa metod bitiminde otomatik olarak kaydedilir. Bu nedenle repository.Update(task) gibi bir kod çağrısına dahi gerek kalmamış oluyor.Burada birçok ayrıntı ve konfigurasyon var ancak varsayılan davranış bu şekildedir.
- Exception Handling: Bir web uygulamasında, bu metod bir Exception fırlatırsa bu Exception otomatik olarak handle edilir, client’ın request türüne göre (AJAX ya da normal request) uygun bir dönüş değeri gönderilir client’a. Client tarafında da bu otomatik olarak handle edilerek kullanıcıya uygun hata mesajı gösterilir. UserFriendlyException özel bir exception türü olup direkt olarak mesaj kullanıcıya gösterilir. Diğer Exception’lar sadece loglanır ve kullanıcıya genel bir hata mesajı gösterilir.
- Logging: UpdateTask metodunun ilk satırında direkt olarak hazır Logger nesnesini kullanarak log yazabiliyoruz. Varsayılan loglama kütüphanesi olarak Log4Net kullanılır.
- Localization: Dikkat edilirse Exception fırlatılırken L adın bir metod kullanıldı. Bu da base class’dan gelen bir metod olup verilen key’e ve o anki kullanıcının diline göre ilgili lokalizasyon metnini verir.
- Auto Mapping: Son satırda ABP’nin MapTo extension metodunu görüyoruz. ABP, Automapper kullanarak bir nesneyi diğerine map edebilir. Böylece gelen input’daki (daha önce validate edilmiş) verilerle Entity’deki property’leri güvenle ezebiliyoruz.
- Dynamic Web API Layer: Bu application service aslında basit bir sınıftır. Browser’dan AJAX’la bunu çağırabilmek için genellikle wrapper şeklinde bir Web API Controller geliştirilir. ABP bu controller’ı runtime’da otomatik yaratır, böylece client’dan doğrudan application service’ler kullanılabilir olur.
- Javascript AJAX Proxy: Dinamik oluşturulan Web API’yi çağırmak için de ABP tarafından yine dinamik olarak bir javascript proxy’si oluşturulur. Böylece javascript’den metod çağırır gibi application service’leri kullanabiliriz.
Görüldüğü gibi çok basit gözüken bu işlem için dahi bütün bunları manuel yapmaya kalsak oldukça zamanımızı alacakken ABP framework tüm bunları otomatik yaparak bizi benzer ve rutin işlemleri tekrar tekrar yapma zahmetinden kurtarır.
Başka?
Bütün bunların dışında aşağıdaki konularda da bize yardımcı olur:
- Modularity: ABP, modüler uygulama geliştirmek için bize güçlü bir altyapı sunar. Kendi paketleri de modül olarak geliştirilmiştir.
- Multi-Tenancy: ABP multi-tenancy destekler. Tek bir veritabanında aynı uygulamayı her müşteri kendi perspektifinden kullanır, birbirinin datasını görmez, kendi rol, kullanıcı ve yetkileri olur.
- Data Filters: Soft-delete gibi pattern’leri kolaylaştırmak için otomatik data filtreleme kullanır. En basit haliyle, eğer gerekiyorsa, Where şartına IsDeleted=False ifadesini otomatik ekler.
- Setting Management: Her uygulamada bazı ayarların kaydedilmesi ve okunması gerekir.
- Domain Events & EventBus: Global domain event’lar tanımlamak, tetiklemek ve yakalamak için altyapı sağlar.
- Unit & Integration Tests: ABP içinde unit ve integration test’leri kolaylaştırmak için gereken temel sınıflar mevcuttur. Bu konudaki makalemeabilirsiniz.
Bunların dışında her yazılımda işimize yarayacak birçok extension metod, helper sınıf ve yapılar mevcuttur.
Başlangıç Şablonu
Yeni bir projeye başlamak, katmanları oluşturmak, gereken nuget paketlerini eklemek, basit bir layout ve menü oluşturup gereken altyapıyı hazırlamak dahi günler alabilen bir iştir.
ABP hazır başlangıç şablonları sayesinde bu iş de oldukça kolaylaşır. Hem SPA (Single-Page Application, AngularJs ya da DurandalJs opsiyonları ile) hem de MPA (Multi-Page Application, yani klasik server taraflı HTML render yapılan MVC) template bulunmaktadır. Ayrıca EntityFramework ya da NHibernate seçimine izin verilir. Template oluşturma sayfasına göz atabilirsiniz.
Bağlantılar
Tüm ABP framework paketleri nuget üzerinden dağıtılmaktadır ve Github üzerindeaçık kaynak kodlu olarak geliştirilmektedir. Aşağıdaki linklerden çok daha detaylı bilgilere ulaşabilirsiniz:
- Web sitesi: http://www.aspnetboilerplate.com
- Forum: http://forum.aspnetboilerplate.com
- Github: https://github.com/aspnetboilerplate
HALİL İBRAHİM KALKAN
Konuk Yazar
5 Comments
Ünal
25 Haziran 2015 at 11:06Hocam Merhabalar,
Sizden bir ricam olacaktı. ASP.NET Boilerplate projesi için örnek modul geliştirme gibi bir örnek video yada döküman paylaşmanız mümkün mü ? Sitesindeki dökümanlar çok kısa yüzeysel olmuş anlamakta zorlanıyorum. Şimdiden teşekkür ederim.
Emre
27 Temmuz 2015 at 17:13Merhabalar,
Site ve içerisindeki makaleler çok güzel emeği geçenlerden Allah razı olsun.
Fakat makale içerisindeki linkleri şans eseri fark ettim.
Kullandığım Browser : Chrome (Diğerlerinde denemedim)
Not:
Lütfen bunu sitem olarak değil öneri olarak görün (genelde böyle önerilerde bulunduğumda ters tepki alıyorum).
Uğur Umutluoğlu
27 Temmuz 2015 at 23:21Merhabalar,
Linkleri şans eseri fark ettim derken linklerin belirgin olmadığını kastediyorsunuz sanırım, doğru mu? Eğer farklı bir durum(kırık/hatalı link vb.) varsa iletebilir misiniz?
Linklerin çok belirgin olmadığını ben de fark ettim, en kısa zamanda farklı bir renkle stil vermeye çalışacağız.
Gani
3 Temmuz 2017 at 01:43Harika iş yapıyorsunuz tebrikler… Yalnız dokümantasyonun aynı zamanda Türkçe’leştirilmesi hususunda çalışma yapılsa çok daha iyi olur. Bu zamana kadar yapılan tüm programlar/ oyunlar vs 10-15 dile çevrilirken bizler (Türkiye olarak) hep dışlanıyoruz. Biraz milliyetçilik gibi olacak ama sektördeki gençlerin bu işle birlikte daha kaliteli platformlar geliştirmesine ya da bir çok konudan haberdar olmasını sağlayacaktır.
Saygılar, başarılarınızın devamını diliyorum. Selametle
Birisi
26 Ekim 2018 at 18:21Boilerplate’in kendi sitesindeki örneği doğrudan almışsınız. Bir entity ile baştan sona nasıl kullnaılırı gösteren bir örnek daha faydalı olurdu.