Bu sayede yazılım geliştirme yapanlar için bazı temel değerler de yaygınlaşmaya başladı.
Bunlardan bazıları "seperation of corserns" ve "decoupling". Yani geliştirilen çözümün parçalarını birbirinden soyutlayarak farklı alanlarda fayda sağlama.
MVC çözüm deseni aslında "stateless" olan web ortamında uygulama geliştirme ihtiyaçlarına ve karşılaşılan problemlere en doğrusu olmasa da daha doğru bir yaklaşım ile çözüm geliştirmek adına tasarlanmıştır.
Fakat 2010 öncesi yaygınlaşmaya başlayan MVC tabanlı çözümler tek bir ihtiyacı karşılıyordu. Adından da anlaşılacak üzere Browser'dan yapılan isteğe View yanıtı dönülmesi.
Diğer bir ihtimal Ajax isteğine yine Action method üzerinden view yanıtı dönülmesiydi.
Mobil telefonların HTML yorumlama ve gösterme kapasiteleri arttıkça aynı Model bilgisini 'User Agent' yani istemcinin kimliğini dikkate alıp istenen tercih edilen View şablonunu dönülmesini sağlayan bir çözüm daha eklendi Asp.Net MVC Framework'üne.
Entegrasyon ihtiyaçları çoğunlukla SOAP standardında çözümler ile karşılanıyordu. MVC ile birlikte bir uyanış gerçekleşti ve bu kadar karmaşık bir çözüme çoğunlukla gerek olmadığına karar verildi. Controller yapısını RESTFULL servisler içinde kullanılabileceği farkedildi. Fakat burada ApiController ile Web sayfaları oluşturmak için geliştirilen çözümün bir benzeri sunuldu.
ASP.Net MVC Core ile birlikte iki farklı çözüme gerek olmadığı kararına varılıp IActionResult sınıfı üzerinden istenen tür de yanıtın istemciye dönülmesine olanak sağlandı.
Fakat burada göz ardı edilen şey aynı türde isteğin farklı istemcilerden yapılabileceği. Yani istek browser tarafından bir web sayfası için yapılmışda olabilir.
Bir mobil uygulama tarafından Json yanıt olarak da istenmiş olabilir. Ürünleri listelediğiniz bir Web sayfası ve mobil uygulama ekranı düşünün.
Birinde sunucudan veriyi (Modeli) HTML ile işleyerek Browser'a iletiyorsunuz. Diğerinde Json olarak dönüyorsunuz ve mobil uygulama kendi üzerinde veriyi işleyip gösteriyor.
Burada problem Controller Action methodunuz tek bir yanıt dönebiliyor.
return View(model) ya da return Json(model)
ActionResult detayları: http://hamidmosalla.com/2017/03/29/asp-net-core-action-results-explained/
Bu durumda seçenekler action method içinde istemcinin kim olduğunun kontrolu ya da iki ayrı action method oluşturmak.
Diğer yöntem ise ASP.Net MVC üzerinde sağlanan Aspect Oriented Programming çözüm yaklaşımı olan Attribute kullanmak. Yani istek geldikten sonra Action method çalıştıkran sonra (sadece return model) ile, gelen isteğe göre yanıtı View yada Json olarak dönmek.
Burada akla gelebilecek ilk soru istemcinin yaptığı isteğe dönülecek veri/yanıt tüm platformlar için (Masaüstü, mobil, Smart Tv...) aynı olması doğru bir çözüm mü ?
Örneğin Masaüstü Browser yanıtında bir listedeki 5 kolon gösterilirken mobil yanıtında 2 gösterilmek istenebilir.
Buradaki tek olumsuzluk eğer mobil tarafta veriyi göstermek için kullanışlı bir çözüm geliştirilmez ise fazladan gidecek veri olacak. Bugünün veri iletişim çözümlerin göze alınca ihmal edilebilir. Görünüyor.
Dolayısıyla buradaki yaklaşım farklı platformlarda uygulamaların benzeri çözüm sağlamaları durumunda farklı Controller ve Action gereksinimleri kalmıyor.
Veya gerekli olduğunda sadece o platform için ek Action sağlanabilir.
İhtiyaçlar
-Global Filter olarak tüm Action'lara uygulanacak.
-Bütün Controller action method lar yanıt olarak model dönecek.
-Var olan "return View(model)" tanımları etkilenmeyecek.
-Json istekleri için (.json) return type Json result olarak değiştirilecek.
-Action Result Model (Object), View yada Json tipinde değilse (Content, OK, Stream ...) yanıt değiştirilmeyecek.
-Sorgulama ekranı gibi filtre verilerinin (örn: Enum) View da oluşturulduğu durumlar için Model üzerinden oluşturulmalı (Örneğin bu şekilde mobil uygulama ekranında da dinamik olarak filtereler oluşur.)
-İstek Modelin doğruluğunun kontrolu ve olumsuz olması durumunda Action çalıştırılmadan standart yanıt dönülmesi ("Single Responsibility principle" itibariyle Farklı bir attribute olması daha doğru olmakla birlikte Action yanıtlarının standartlaştırılması adına birlikte de kullanılabilir)
-Exception durumunda yine istek yanıt tipine göre standart yanıt dönülmesi. (Bu attribute içinde uygulanmadı). Sunucu hata kodu neyse istemciye de aynı kodun dönülmesi.
-Authorize kullanımı durumunda (Cookie oturumu ile giriş için oturum açma sayfasına yönlendirme), Identity ayarlarında sadece Json yanıt dönen veya .json extension istekleri için yönlendirmenin iptali ve istemciye Http 401 yanıtının dönülmesi. Örnek tanımlar;
services.ConfigureApplicationCookie(options =>
{
options.Events = //>> If Request is coming to /Api, do not redirect due to authantication
new CookieAuthenticationEvents
{
OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/Api") && context.Response.StatusCode == (int)HttpStatusCode.OK)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
}
else
{
context.Response.Redirect(context.RedirectUri);
}
return Task.FromResult
}
};
});
Kullanım için:
-Api istekleri .json şeklinde yapılmalı. Örn: /list ve /list.json
-Controller default root ajax isteğinde /Home/Index.json olarak kullanılmalı
-route tanımlarına format içeren tanım eklenmeli
- .MapRoute(
name: "defaultWithExtension",
template: "{controller=Home}/{action=Index}.{format}/{id?}")
-servislerlere eklenmesi: services.AddTransient
services.Configure
{
options.Filters.Add(typeof(Web.Filters.FormatResponseResultFilterAttribute));
});
Hiç yorum yok:
Yorum Gönder