C#nedir?com
 
YAZAR HAKKINDA
Önsel Akın
Önsel Akın
http://nslkn.com
İletişme geçmek için tıklayın.
8 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: ASP.NET MVC 2 ControllerActionInvoker ControllerFactory DefaultModelBinder FormValueProvider IModelBinder IValueProvider Model Binder MVC MvcHandler QueryStringValueProvider RouteDataValueProvider Validation Value Provider ASP.NET Önsel Akın
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : Orta
Kategori : ASP.NET
Yayınlanma Tarihi : 18.8.2010
Okunma Sayısı : 48269
Yorum Sayısı : 3     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
XML - Deniz Kılınç
emre TAŞ
yazının devamı >
emre TAŞ
Decompiling and Reverse Engineering .Net Radyo
emre TAŞ
yazının devamı >
emre TAŞ
Masaüstü mü ? İnternet Mi? .Net Radyo
emre TAŞ
yazının devamı >
emre TAŞ
.Net Kavramları - .Net Radyo
emre TAŞ
yazının devamı >
emre TAŞ
Yeni Başlayanlar için - .Net Radyo
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Burak Selim Şenyurt
Asp.Net Core'da Bir WebSocket Macerası 21.10.2017
Burak Selim Şenyurt
.NET Core 2.0 ile Basit Bir Web API Geliştirmek 21.10.2017
Turhal Temizer 'in Blogu
ChatBot UI Sample 21.10.2017
Turhal Temizer 'in Blogu
C# – IRR Function 21.10.2017
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
ASP.NET MVC2 - Model Bağlayıcılar ve Değer Sağlayıcılar
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon

Model bağlayıcı nedir?

Bİldiğiniz gibi ASP.NET MVC çatısında yönetici (controller) aksiyonlarına (action) gelen tüm parametreler aslen string veri tipindedir. Gelen değerin string veri tipinden, aksiyon parametresinin sahip olduğu veri tipine döndürülmesinden ve istemciden gelen değerin bu parametre içinde saklanmasından sorumlu olan sınıf(lar) model bağlayıcı (model binder) olarak isimlendirilmektedir. Karmaşık veri tipleri, listeler, koleksiyonlar, diziler, binary byte dizileri standart model bağlayıcılar tarafından tanınabilir.

MVC'de talep (request) önce MVCHandler nesnesine gelir. MVCHandler, bir yönetici fabrikası (ControllerFactory) aracılığıyla bir yönetici elde eder ve talebi yöneticiye yönlendirir. Gelen talebe göre yönlendirme (routing) kayıtlarına bakılarak ilgili yöneticinin ilgili aksiyonu ControllerActionInvoker nesnesi tarafından çağrılır. Bu çağrı sırasında hem aksiyon için kayıt edilmiş aksiyon filtrelerine (action filter) göre işlem gerçekleştirilir hem de aksiyon parametrelerine uygun bir şekilde gelen talep içerisinden veriler ayıklanır ve en başta da anlattığım gibi string veriler aksiyon parametrelerine uygun veri tiplerine döndürülerek veri atamaları gerçekleşir. Bu veri tipi dönüşümü ve veri atamalarından sorumlu olan en önemli bileşen ise bir DefaultModelBinder nesnesidir. DefaultModelBinder, IValueProvider nesnelerinden faydalanarak gelen değerleri okur ve hem standart .Net veri tiplerine sahip değerleri hem de karmaşık nesneleri oluşturabilir. MVC paketinde hazır gelmekte olan dört farklı IValueProvider nesnesi vardır. Bunlar talep geldiğinde işleme alınma sıralarına göre şu şekilde listelenebilir;

Değer Sağlayıcı Değer Kaynağı Üst Sınıf
FormValueProvider Request.Form NameValueCollectionValueProvider
RouteDataValueProvider RouteData.Values IDictionaryValueProvider<object>
QueryStringValueProvider Request.QueryString NameValueCollectionValueProvider
HttpFileCollectionValueProvider Request.Files DictionaryValueProvider<HttpPostedFileBase>

Şimdi farklı aksiyon parametrelerine göre model bağlama nasıl çalışıyor inceleyelim.

Primitif veri tipleri ve model bağlama

public ActionResult Login(string userName, string eMail, bool persist) {}

Yukarıdaki aksiyonda talep içinden bilgilerin alınması ve aynı isimdeki parametrelere atanması DefaultModelBinder için en kolay işlemlerden biri. Burada dikkat edilmesi gereken noktalardan biri, bool persist olarak tanımlanmış parametrenin Nullable olmamasıdır. Dolayısıyla eğer DefaultModelBinder model bağlama sırasında hiçbir değer sağlayıcı nesne ile persist parametresine değer ataması gerçekleştiremezse (ki bu sadece istemciden bu isimde bir değer gelmemesi sonucunda olur) bu durumda bir InvalidOperationException ile karşılaşırız. Nullable olmayan veri tipleri için CSharp 4.0 opsiyonel parametre özelliğinden faydalanabilirsiniz. Yani yukarıdaki aksiyon tanımını;

public ActionResult Login(string userName, string eMail, bool persist = false) { … }

şeklinde yazarak, persist değeri gelmediğinde ön ayarlı değer olarak false olmasını sağlayabilirsiniz.

Kullanıcı tanımlı tipler ve model bağlama

Tanımı aşağıdaki gibi olan bir modelimiz olsun;

public class SuperModel { public string FirstName { get; set; } public string LastName { get; set; } public int Height { get; set; } public int Bust { get; set; } public int Waist { get; set; } public int Hips { get; set; } }

Bu modeli bir aksiyon parametresi olarak kullandığımız takdirde (tabi ki bir form postalama senaryosu dahilinde bu olmalı), DefaultModelBinder devreye girecek ve bir SuperModel nesnesi oluşturacak, istemciden postalanan verilerle SuperModel nesnesinin tüm özelliklerini dolduracaktır. Böylece okumak istediğiniz her değer için model.FirstName = Request.Form["FirstName"] benzeri gereksiz tekrarlamalara girmemiş olacağız.

Aşağıda SuperModel modeliyle çalışan bir aksiyon tanımı mevcut;

public ActionResult SaveModel(SuperModel superModel) { ... }

Model bağlama işleminde seçici geçirgenlik

Veritabanına süper model kayıt etmeyi sağlayan bir html formumuz olduğunu varsayalım. Sorumlu kişi bu form ile ad, soyad, boy ve beden ölçüleriyle birlikte süper model kayıtları oluşturuyor. Süper modelin boyunun sorumlu kişi tarafından kayıt edilmesini istemiyoruz. Aksiyonumuz hemen yukarıdaki şekilde tanımlanmış yani SuperModel parametresiyle çalışıyor. Height bilgisinin DefaultModelBinder tarafından algılanmasını engellemek için görünümdeki html formundan Height için oluşturulmuş olan input kontrolünü kaldırıyoruz. Yani form aşağıdaki şekilde tanımlanıyor;

<h2>SaveModel</h2>

<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>

<fieldset>
<legend>Fields</legend>

<div class="editor-label">
<%: Html.LabelFor(model => model.FirstName) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.FirstName) %>
<%: Html.ValidationMessageFor(model => model.FirstName) %>
</div>

<div class="editor-label">
<%: Html.LabelFor(model => model.LastName) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.LastName) %>
<%: Html.ValidationMessageFor(model => model.LastName) %>
</div>

<div class="editor-label">
<%: Html.LabelFor(model => model.Bust) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Bust) %>
<%: Html.ValidationMessageFor(model => model.Bust) %>
</div>

<div class="editor-label">
<%: Html.LabelFor(model => model.Waist) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Waist) %>
<%: Html.ValidationMessageFor(model => model.Waist) %>
</div>

<div class="editor-label">
<%: Html.LabelFor(model => model.Hips) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Hips) %>
<%: Html.ValidationMessageFor(model => model.Hips) %>
</div>

<p>
<input type="submit" value="Create" />
</p>
</fieldset>

<% } %>

Form tanımında Height parametresine ait bir tanım olmadığına dikkat edin. Kullanıcı tarafından Height değerinin girilmesini engellemiş oluyoruz, ancak gerçekten Height değerinin alınmasına engel oluyor muyuz? Hayır olmuyoruz. Kullanıcı kayıt formunu postalarken, iyi niyetli bir kullanıcı(!) ise, action url parametresine ?Height=178 parametresini ekleyerek kayıt ettiği süper modelin 1.78 boyunda olmasını sağlayabilir. DefaultModelBinder, Request.Form içinde bulamadığı Height değerini, Request.QueryString içinden alacak ve dinamik olarak oluşturduğu SuperModel nesnesine bağlayacaktır. DefaultModelBinder'a Height parametresini bağlama işleminin dışında tutmasını bildirmek için Bind öz niteliğini kullanıyoruz. Güncel aksiyon tanımımız şu şekilde;

public ActionResult SaveModel([Bind(Exclude = "Height")]SuperModel superModel) { ... }

Eğer Height parametresini sadece SaveModel aksiyonu için değil, SuperModel nesnesinin kullanıldığı her aksiyonda bağlama işlemi dışında bırakmak istiyorsak, bu durumda Bind öz niteliğini sınıf üzerinde kullanabiliriz;

[Bind(Exclude = "Height")] public class SuperModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Height { get; set; }
public int Bust { get; set; }
public int Waist { get; set; }
public int Hips { get; set; }
}

Model bağlama ve koleksiyonlar

DefaultModelBinder sadece primitif ve kullanıcı tanımlı veri tipleri ile çalışmıyor. Kullanıcı tarafından post edilen verilerden diziler, koleksiyonlar ve sözlükler oluştururabilme yeteneğine de sahiptir. Birkaç örnekle bu özellikleri inceleyelim.

Aşağıda üç adet checkbox içeren bir form tanımı görüyorsunuz. Üç checkbox'ın da name özelliği, yani isimleri aynı; source.

<% using (Html.BeginForm()) { %>

Gazete: <input type="checkbox" name="source" value="gazete" /><br />
Arama Motoru: <input type="checkbox" name="source" value="arama_motoru" /><br />
Reklam: <input type="checkbox" name="source" value="reklam" /><br />

<input type="submit" value="Gönder Bakalım" />
<% } %>

Formdan gelen bilgiyi alacak olan aksiyon tanımı da hemen aşağıda:

public ActionResult Registration(List<string> source) { ... }

Bu sayfaya gidip, karşımıza gelen formdaki üç checkbox'tan örneğin sadece Arama Motoru ve Reklam kutucuklarını işaretleyip formu postaladığımızda, aksiyondaki source parametresinde iki farklı string olduğunu ve sırasıyla değerlerinin arama_motoru ve reklam olduğunu göreceğiz. DefaultModelBinder, formdan gelen ve aynı isme sahip olan değerleri FormValueProvider kullanarak bir string listesine attı ve böylece biz de teker teker seçilmiş olan değerlere ulaşabildik.

Son bir örnek olarak, az önce yaptığımız string listesi uygulamasını süper modellerimizle gerçekleştirelim. Bir dizi süper model bilgisini form üzerinden sunucuya postalayan bir görünüm ve postalanmış bilgiler içinden süper modelleri ayıklayabilecek bir aksiyon tanımı yapalım.

<h2>SaveModels</h2>

<% using (Html.BeginForm()) { %>

<% for (int i = 0; i < 10; i++) { %>

<fieldset>
<legend><%: i %>. Süper Model</legend>

<div class="editor-label">
<%: Html.Label(string.Format("model[{0}].FirstName", i)) %>
</div>
<div class="editor-field">
<%: Html.TextBox(string.Format("model[{0}].FirstName", i)) %>
</div>

<div class="editor-label">
<%: Html.Label(string.Format("model[{0}].LastName", i)) %>
</div>
<div class="editor-field">
<%: Html.TextBox(string.Format("model[{0}].LastName", i)) %>
</div>

<div class="editor-label">
<%: Html.Label(string.Format("model[{0}].Bust", i)) %>
</div>
<div class="editor-field">
<%: Html.TextBox(string.Format("model[{0}].Bust", i)) %>
</div>

<div class="editor-label">
<%: Html.Label(string.Format("model[{0}].Waist", i)) %>
</div>
<div class="editor-field">
<%: Html.TextBox(string.Format("model[{0}].Waist", i)) %>
</div>

<div class="editor-label">
<%: Html.Label(string.Format("model[{0}].Hips", i)) %>
</div>
<div class="editor-field">
<%: Html.TextBox(string.Format("model[{0}].Hips", i)) %>
</div>

</fieldset>

<% } %>

<p>
<input type="submit" value="Create" />
</p>

<% } %>

Yukarıdaki form tanımında bir döngü ile 10 adet süper model kaydı yapılabilmesi için kontrol serisi oluşturuyorum. Kontrollerin isimlendirmesine lütfen dikkat. Her bir model için model[0].FirstName, model[5].Waist şeklinde isimleri olan input kontrolleri oluşturmuş oluyorum. input kontrollerine bu şekilde isim vermek tamamen kurallar dahilinde. DefaultModelBinder, dizi şeklinde bir isimlendirmeyle karşılaştığında, aksiyon parametresi ile eşleştirmek için indeksleyicilerin hemen önündeki ismi parametre ismi olarak alıyor, yani bizim senaryomuzda aksiyon parametresinin adı model olmalı.

Aşağıda aksiyon tanımı mevcut:

[HttpPost] public ActionResult SaveModels(List<SuperModel> model)
{
return View();
}

Form postalandığında, DefaultModelBinder devreye giriyor, postalanan verilerden sırasıyla 10 adet SuperModel nesnesi oluşturuyor ve her bir fieldset içinden gelen veriyi bir SuperModel nesnesine bağlıyor. Gördüğünüz gibi çok dinamik ve esnek bir yapı mevcut. ASP.NET Webforms yapısından çok daha esnek.

Konumuz burada bitmez. Zira model bağlayıcı ve değer sağlayıcı konusu üzerinde daha konuşulabilecek bir konu. İlerleyen yazılarda, MVC'nin her noktasında olduğu gibi bu sistemi nasıl genişletebiliriz, IValueProvider ve IModelBinder arayüzlerini kullanarak nasıl model bağlayıcı ve değer sağlayıcı geliştirebiliriz inceleyeceğiz.

Makale:
ASP.NET MVC2 - Model Bağlayıcılar ve Değer Sağlayıcılar ASP.NET Önsel Akın
  • Yazılan Yorumlar
  • Yorum Yaz
TEM
5
2016
Çok başarılı ve anlaşılır bir yazı olmuş.
OCA
19
2011
Bilgilendirme için teşekürler. TDK Büyük Sözlük'te aksiyon kelimesinin İngilizce'den gelen karşılıkları için verilmiş olan açıklamalardan ilkini buraya yapıştırıyorum: "1. Eylem: Bir iş, hareket yapmak, bir davranışta bulunmak."
OCA
19
2011
Yazı için teşekkürler aşırı derecede gözüme batan bir nokta var kusura bakmazsanız onu düzeltmek istiyorum.Bir anlam yanlışı var ve yazı içinde o kadar tekrar edilmiş ki benim bile ağzıma yerleşti. Action kelimesi aksiyon demek değildir.Zaten mantıken aksiyon çok saçma olur.Action = Hareket, Eylem, Faliyet anlamına gelir.Aksiyon kelimesiyle uzaktan yakından alakası yoktur. İyi çalışmalar.
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor