ASP.NET 5 Web API Model ve ViewModel Sınıflarını Automapper ile Eşleştirme
Automapper Nedir?
Asp.Net 5 ve önceki MVC sürümlerinde veritabanı kullanarak web uygulamalarını geliştirirken çoğunlukla (özellikle küçük ve orta ölçekli uygulamalar için) Entity Framework ile geliştirme yapıyoruz. Entity Framework ile geliştirme yaparken model kullanımında iki farklı yöntem izleniyor.
1. Entity için oluşturulan modeller View’lar için de kullanılıyor.
2. Entity için oluşturulan modeller ile beraber View’lar üzerinde işlem yapmak için ViewModel’ler oluşturuluyor. ViewModel’ler aracılığıyla alınan ya da gönderilen veriler, Entity Data modellerine arkaplanda aktarılıp veritabanı işlemleri yapılıyor. Ya da tam tersi yöntemle veritabanından Entity data modeller ile alınan veriler, ViewModel’lere aktarılıp View’lar üzerinde işleniyor.
İkinci yöntem (ki daha doğru olan yöntem) kullanılırken Entity Data model ile ViewModel arasındaki aktarım işlemi elle yapılabileceği gibi, Automapper kullanılarak çift yönlü otomatik hale de getirilebilir. Automapper, nuget üzerinden indirilip projeye dahil edilen, object – object mapping (nesne – nesne eşleştirme) işlemini yapan bir API’dir.
Automapper ile ilgili detaylı bilgi için nuget’teki sayfasına buradan ulaşabilirsiniz: https://www.nuget.org/packages/AutoMapper/
Automapper ile mapping işleminin nasıl yapıldığını bir örnek uygulama üzerinde işlemlerimizi gerçekleştirelim. Örnek uygulamamız bir Web API uygulaması olacaktır.
Örnek Uygulama
Örneğimizde müşterilerimiz (Customer) ve müşterilerin verdiği siparişler (Order) olacaktır. Bir müşterinin birden fazla sipariş verebileceği düşünülerek müşteri ve sipariş arasında ilişki de oluşturacağız.
Sipariş bilgilerini tanımlayacağımız Order isimli bir model oluşturalım. İçerisinde sipariş zamanı (OrderDate), sipariş tutarı (TotalPrice), sipariş durumu (Status) özellikleri olsun.
public class Order { public int Id { get; set; } public DateTime OrderDate { get; set; } public double TotalPrice { get; set; } public string Status { get; set; } }
Müşteri bilgilerini tanımlayacağımız Customer isimli bir model oluşturalım. İçerisinde adı (FirstName), soyadı (LastName), yaşadığı ülke (Country), şehir (City), e-posta adresi (Email) özellikleri olsun. Bu özelliklerin yanı sıra, bir müşteri birden fazla sipariş verebileceği için Order modeli ile ilişkiyi de ekleyelim.
public class Customer { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Country { get; set; } public string City { get; set; } public string Email { get; set; } public string Phone{ get; set; } public ICollection<Order> Orders { get; set; } }
Modelleri oluşturduktan sonra CustomerController isminde Web API controller sınıfını oluşturalım. Controller sınıfına müşteri bilgilerini Json formatında döndüren (geri dönüş tipi JsonResult olan) GetCustomers isimli bir metod ekleyelim. Metod içinde Customer listesinde dummy müşteri ve sipariş kayıtlar oluşturup Json formatında dönelim.
public class CustomerController : Controller { [HttpGet("api/customers")] public JsonResult GetCustomers() { List<Customer> customerList = new List<Customer>(); Customer ugur = new Customer() { Id = 1, Name = "Veysel Ugur KIZMAZ", Country = "Turkey", Email = "veysel@ugurkizmaz.com", Orders = new List<Order> { new Order { Id = 1, OrderDate = new DateTime(2015,10,01), TotalPrice = 100, Status = "Shipped" }, new Order { Id = 3, OrderDate = new DateTime(2015,10,18), TotalPrice = 85, Status = "Shipped" } } }; customerList.Add(ugur); Customer baran = new Customer() { Id = 2, Name = "Baran Yağış KIZMAZ", Country = "Turkey", Email = "baranyagis@kizmaz.org", Orders = new List<Order> { new Order { Id = 2, OrderDate = new DateTime(2015,10,12), TotalPrice = 388, Status = "Shipped" }, new Order { Id = 4, OrderDate = new DateTime(2016,01,05), TotalPrice = 649, Status = "new" } } }; customerList.Add(baran); return Json(customerList); } }
Kodlamayı tamamladıktan sonra Postman ile Web Api metodunu çağırdığımızda, dummy oluşturduğumuz kayıtların Json formatında geldiğini görebiliriz.
Bu örnekte, 1. maddede anlattığımız model kullanımını uyguladık. Şimdi 2. maddede belirttiğimiz model kullanımını uygulamak için ViewModels dizininin altına CustomerViewModel isminde bir model sınıfı oluşturalım. Bu sınıfta sadece müşterinin adı ve ülkesi bilgileri olsun.
public class CustomerViewModel { public int Id { get; set; } public string Name { get; set; } public string Country { get; set; } }
GetCustomer actionından Customer listesi yerine CustomerViewModel listesi dönelim. Bunun için şu anki bilgilerimizle yapacağımız işlem aşağıdaki şekilde olacaktır:
List<CustomerViewModel> customerResultList = customerList.Select(c => new CustomerViewModel { Id = c.Id, Name = c.Name, Country = c.Country }).ToList();
Her işlemden önce / sonra bu şekilde verileri birbirine dönüştürme, hem kodlama açısından bir maliyet getirecek, hem de model güncellemelerinde hata yapma riskini artıracaktır. Bunun için Automapper ile bu işlem nasıl yapılır, öğrenelim.
ASP.NET 5 Projesine Automapper Kurulumu
Automapper paketi, başta da belirtildiği gibi nuget üzerinden yüklenen bir pakettir. Bu sebeple project.json dosyası üzerinden bu paketi projeye ekleyebiliriz. “AutoMapper” paketini projeye aşağıdaki şekilde aratarak ekleyelim.
ASP.NET 5 Projesinde AutoMapper ile Model Mapping Tanımlaması
AutoMapper paketini projeye ekledikten sonra Startup sınıfının Configure metoduna gelelim ve hangi sınıfların eşleştirileceğini tanımlayalım. Eşleştirme işlemi için Mapper sınıfının Initialize metodunu kullanıyoruz. Parametresinde ise eşleştirme işlemlerini tanımlayacağız.
Mapping tanımlamasını, generic bir metod olan CreateMap<TSource, TDestination> metodu ile, hangi sınıfın hangi sınıfla (TSource, TDestination) eşleşeceğini belirterek gerçekleştireceğiz. Çift yönlü eşleştirme istiyorsak ReverseMap metodunu da tanımlamanın sonuna eklememiz gerekiyor. Tek yönlü eşleştirme (TSource modelinden TDestination modeline) istiyorsak ek bir işlem yapmamıza gerek olmayacaktır.
Customer modelindne CustomerViewModel modeline çift yönlü mapping tanımlamasını yapalım.
public void Configure(IApplicationBuilder app) { app.UseMvc(); Mapper.Initialize(mapping => { mapping.CreateMap<Customer, CustomerViewModel>().ReverseMap(); }); }
Benzer şekilde varsa bütün mapping tanımlamalarını burada alt alta yapmanız gerekmektedir.
ASP.NET 5 Projesinde AutoMapper ile Model Dönüştürme
Tanımlamayı yaptktan sonra CustomerController sınıfına gelelim ve GetCustomers actionının geri dönüş değerini AutoMapper’ı da kullanarak CustomerViewModel’e dönüştürelim. Bu işlem için Mapper sınıfının Map<TDestination> metodunu kullanıyoruz. TDestination tanımına, veriyi dönüştüreceğimiz veri türünü belirtiyoruz.
NOT: Eğer verimiz tek bir nesne ise veri türünü yazmamız yeterli olacaktır. Eğer bir listeyi (List<T>) dönüştürmemiz gerekiyorsa, verinin bir IEnumerable veri olduğunu belirtmek için TDestination tanımını IEnumerable<T> şeklinde yapmamız gerekiyor. Örnek uygulamada verimiz liste olduğu için IEnumerable<T> tanımlamasını yapacağız.
var customerListAsCustomerViewModel = Mapper.Map<IEnumerable<CustomerViewModel>>(customerList);
Dönüşüm işlemini yaptıktan sonra geriye customerListAsCustomerViewModel nesnesini Json formatında döndüreceğiz. Kodlamayı tamamladığımızda GetCustomers actionının tüm kodları aşağıdaki gibi olacaktır.
[HttpGet("api/customers")] public JsonResult GetCustomers() { List<Customer> customerList = new List<Customer>(); Customer ugur = new Customer() { Id = 1, Name = "Veysel Ugur KIZMAZ", Country = "Turkey", Email = "veysel@ugurkizmaz.com", Orders = new List<Order> { new Order { Id = 1, OrderDate = new DateTime(2015,10,01), TotalPrice = 100, Status = "Shipped" }, new Order { Id = 3, OrderDate = new DateTime(2015,10,18), TotalPrice = 85, Status = "Shipped" } } }; customerList.Add(ugur); Customer baran = new Customer() { Id = 2, Name = "Baran Yağış KIZMAZ", Country = "Turkey", Email = "baranyagis@kizmaz.org", Orders = new List<Order> { new Order { Id = 2, OrderDate = new DateTime(2015,10,12), TotalPrice = 388, Status = "Shipped" }, new Order { Id = 4, OrderDate = new DateTime(2016,01,05), TotalPrice = 649, Status = "new" } } }; customerList.Add(baran); var customerListAsCustomerViewModel = Mapper.Map<IEnumerable<CustomerViewModel>>(customerList); return Json(customerListAsCustomerViewModel); }
Kodlamayı tanımladıktan sonra projeyi yeniden derleyip çalıştıralım ve verileri sorgulayalım. Verilerin CustomerViewModel türünden geldiğini göreceksiniz.
Son satıra breakpoint ekleyerek customerListAsCustomerViewModel değişkenindeki elemanları da inceleyebilirsiniz.