Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Asp.NET MVC – Bir View’da Tuple Sınıfı İle Çoklu Model Kullanımı

Yürüyorsan koşabilmelisin, koşuyorsan uçabilmelisin, uçuyorsan ışınlanabilmelisin.Durmamalısın.Bu günün, dününden bir adım ileri olmalı, tarihle yarışmalı, yarına daha çetin bir maratonla başlamalısın.Bu yaşadığımız çağın gereksinimlerindendir.Öyleyse işinde de çığır açmalısın.Evet, bu yazımızda Asp.NET MVC’de (şahsen)mimarisel mantığı aşmak için çabalayacağız.Peki nedir bu yazımızın içeriği? diye sorarsanız eğer hemen izah edeyim.Biliyorsunuz ki, Asp.NET MVC mantığı kullanıcıdan gelen(View) talep Controller’da gerekli veritabanı işlemleri(Model) ile işlenir ve geri kullanıcıya yani View’a cevap gönderilir.Bu genel mimarisel yapıda, View katmanında sadece bir adet Model kullanma hakkımız vardır.Tabi ki de, binbir türlü teknikle birden fazla model kullanabilme şerefine nail olabiliriz ama ben şuana kadar gördüğüm en gözde tekniği sizlerle paylaşacağım.Haliyle bu profesyonel teknik sayesinde Asp.NET MVC mimarisinde ki bu sınırı aşmış olduğumuzu düşündüğüm için yazımıza böyle bir heyecanla giriş yapmak istedim.

Tuple sınıfı ile bir View’a birden fazla model tanımlayabiliriz.Tabi, mevzuya giriş yapmadan önce neden stabil tekniklerin işe yaramadığını izaha öncelik tanıyacağız.

Makalemizde örneklendirme amaçlı aşağıdaki “Okul” ve “Ogretmen” isimli iki modeli baştan oluşturuyorum.

    class Okul
    {
        public string OkulAdi { get; set; }
    }
    class Ogretmen
    {
        public string Adi { get; set; }
        public string SoyAdi { get; set; }
        public string Bransi { get; set; }
        public double Maasi { get; set; }
    }

Senaryomuz şöyle olacaktır.Bir formda öğretmenle ilgili bilgileri post ederken okul bilgiside post edilecektir lakin öğretmenle ilgili bilgileri “Ogretmen” isimli, okul bilgilerini ise “Okul” isimli modelimiz tutacaktır.Bu işlemi gerçekleştirebilmemiz için View’da iki adet model tanımlaması yapmamız gerekmektedir.Tabi bu teknik olarak mümkün olmadığı için şimdi sizlere basit mantık tekniği göstereceğim ve bu tekniğin her zaman işe yaramadığını anlatmaya çalışacağım.

@using WebApplication14.Models

@model Ogretmen

@using (Html.BeginForm("Post", "Home", FormMethod.Post))
{
    @:Adı:
    @Html.TextBoxFor(model => model.Adi)
    <br />
    @:Soyadı:
    @Html.TextBoxFor(model => model.SoyAdi)
    <br />
    @:Maaşı:
    @Html.TextBoxFor(model => model.Maasi)
    <br />
    @:Branşı:
    @Html.TextBoxFor(model => model.Bransi)
    <br />
    @:Okulu:
    @Html.TextBoxFor(model => model.Okul.OkulAdi)

    <input type="submit" value="Post Et" />
}

Yukarıdaki View dosyasına bakarsanız eğer öğretmen formu oluşturulmuştur.Ayriyetten Ogretmen modeli üzerinden Okul tipinde bir property tanımlanmış ve o özellikle de okul bilgisi tutulmaya çalışılmıştır.

Bu işlemi yapabilmek için Ogretmen modeline aşağıdaki kod ekini yapmamızy yeterlidir.

    public class Ogretmen
    {
        public string Adi { get; set; }
        public string SoyAdi { get; set; }
        public string Bransi { get; set; }
        public double Maasi { get; set; }

        public Okul Okul { get; set; }
    }

Bu şekilde kullanılan bir model tasarımında bakalım nasıl bir durumla karşı karşıya kalıyoruz.

Asp.NET MVC - Bir View'da Tuple İle Çoklu Model Kullanımı

Yukarıda yaptığımız teknik sayesinde bir View’da birden fazla model kullanmış olduk.Bu şekilde bir kullanım teknik olarak mümkündür.Lakin proje ilerledikçe bu tekniğin kullanımında istemsiz sıkıntılar doğmakta ve yer yer Model içindeki tanımlanan referansa gönderilen değerler alınamayıp, null değerler dönebilmektedir.İşte bu olası durumu hiç yaşamadan Tuple sınıfıyla daha profesyonel çoklu model kullanımını görelim.

Modellerimizi ilk tanımladığımız haline getirdikten sonra View’ı kullandığımız Controller’da ki Action metotda aşağıdaki işlevi gerçekleştirelim.’Örneğimizde HomeController’da ki Index Action metodudur.’

        public ActionResult Index()
        {
            return View(Tuple.Create<Okul, Ogretmen>(new Okul(), new Ogretmen()));
        }

Burada gördüğünüz gibi Tuple sınıfının referansı üzerinden Create metodu sayesinde çoklu model kullanacağımız View’a modellerimizi tanımlıyoruz.

@using WebApplication14.Models

@model Tuple<Okul, Ogretmen>

@using (Html.BeginForm("Post", "Home", FormMethod.Post))
{
    @:Adı:
    @Html.TextBoxFor(model => model.Item2.Adi)
    <br />
        @:Soyadı:
        @Html.TextBoxFor(model => model.Item2.SoyAdi)
        <br />
        @:Maaşı:
        @Html.TextBoxFor(model => model.Item2.Maasi)
        <br />
        @:Branşı:
        @Html.TextBoxFor(model => model.Item2.Bransi)
        <br />
        @:Okulu:
        @Html.TextBoxFor(model => model.Item1.OkulAdi)

        <input type="submit" value="Post Et" />
}

View katmanında yukarıdaki örnek kodda da gördüğünüz gibi modelimizi Controller’da gönderdiğimiz nesne formatında, Tuple biçiminde tanımlıyoruz.
Bu tanımlamadan sonra “Model” komutuna nokta(.) dediğimizde “Item1” özelliği ilk parametredeki nesneyi, “Item2” özelliği de ikinci parametredeki nesneyi sembolize etmektedir.Tuple sınıfı ile 8 adet parametre tanımlayabiliriz.Bu demek oluyor ki, bir View’a 8 adet model gönderebilme olanağımız var demektir.

        [HttpPost]
        public ActionResult Post([Bind(Prefix = "Item1")]Okul Model1, [Bind(Prefix = "Item2")]Ogretmen Model2)
        {
            return View();
        }

Formun post işlemi neticesinde HttpPost Attribute’u ile işaretlenmiş Action metoduna da yukarıdaki gibi parametre tanımlaması yapıyoruz.Burada post neticesinde Tuple sınıfıdan gelen parametleri, Action metodumuzdaki parametrelere Bind ediyoruz.”Prefix” özelliği ile, işaretlenen parametrenin Tuple’da ki hangi özelliği sembolize edeceğini belirtiyoruz.Yukarıdaki örneğimizde “Item1” özelliğini “Okul” parametresinin temsil etmesini söylüyoruz.Bunun sebebi, Tuple sınıfını tanımlarken “Item1” özelliğine “Okul” nesnesini tanımlamış olmamızdır.

Bu teknikle yapılandırılan post işlemini Break – Point ile gözlemlersek eğer;
Asp.NET MVC - Bir View'da Tuple İle Çoklu Model Kullanımı - 2
Asp.NET MVC - Bir View'da Tuple İle Çoklu Model Kullanımı - 3

Ekran görüntülerinden de gördüğünüz gibi iki nesnemizide bilgileri yakalamış bir vaziyette elde etmiş oluyoruz.Bu şekilde bir kullanım oldukça esneklik sağlamakta ve profesyonel bir teknik edası sergilemektedir.

Son olarak, post anında çalışan Action metodda parametrelere Bind işlemini göz ardı ederseniz eğer post işleminden sonra sayfanın kaynak kodlarıyla karşılaşmanız muhtemeldir.Buna dikkat ediniz 😉

Bol bol faydalanmanız dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar dilerim…

Bunlar da hoşunuza gidebilir...

17 Cevaplar

  1. ahmet dedi ki:

    Parametredeki bind nedir?

    • Gençay dedi ki:

      Sorunuzun cevabı makalemizin içeriğinde bulunmasına rağmen tekrardan izah ediyorum.
      Tuple tipindeki modeli post ettiğiniz zaman Action metotda direkt Tuple tipinden almanıza gerek yoktur.Yazımızın içeriğinde ki kodu baz alalım.

      [HttpPost]
      public ActionResult Post([Bind(Prefix = "Item1")]Okul Model1, [Bind(Prefix = "Item2")]Ogretmen Model2)
      {
          return View();
      }
      

      Varsayalım, View’de Post işlemi gerçekleştirildi ve yukarıdaki Action metot tetiklendi.İşte bu durumda Tuple nesnesi üzerinde taşınan nesneleri Bind ile metodun parametresindeki ilgili alanlara tanımlıyoruz.Yukarıda gördüğünüz gibi Bind bir Attribute’dur.Bu Attribute’un Prefix özelliğini kullanarak bu işlemi gerçekleştiriyoruz.

      [Bind(Prefix = “Item1”)] = “Tuple nesnesindeki Item1 isimli özellik aslında bir Okul nesnesini temsil etmektedir ve bu temsil edilen nesneyi bu parametreye tanımla!” demiş oluyoruz.

      Aynı şekilde Item2 isimli özellikte bir Ogretmen nesnesini temsil ettiği için Prefix ile ilgili parametreye tanımlamış oluyoruz.

  2. ahmet dedi ki:

    cevap için teşekkürler. web apide [Formbody] diye bir parametre kullanılıyor nedir? birde token authentication ile ilgili bir blog yazınız varmı ?

  3. Halil te. dedi ki:

    Gençay bey merhaba. foreach ile view de listeleme yapmak istiyorum. ama hata veriyor. şu şekilde:
    —————————————
    ‘/’ Uygulamasında Sunucu Hatası.

    Derleme Hatası

    Açıklama: Bu isteği yerine getirmek için gereken kaynak derlenirken bir hata oluştu. Lütfen aşağıdaki özel hata ayrıntılarını gözden geçirin ve kaynak kodunuzu uygun biçimde değiştirin.

    Derleyici Hata İletisi: CS1579: foreach statement cannot operate on variables of type ‘System.Tuple’ because ‘System.Tuple’ does not contain a public definition for ‘GetEnumerator’

    Kaynak Hatası:

    Satır 7: }
    Satır 8:
    Satır 9: @foreach (Tuple tuple in Model)
    Satır 10: {
    Satır 11:

    Kaynak Dosya: D:\mvc çalışmaları\tuple\tuple\tuple\Views\Home\Post.cshtml Satır: 9
    ————-

  4. gökhan aydın dedi ki:

    Merhaba

    Halil te. arkadaşımızla benzer sorun bende yaşıyorum. Kendisi kodları göndermemiş, ben göndereyim

    View:

    @model Tuple
    @foreach (sp_VideoArama_Result item in Model.Item2)
                        { 
                            @item.Headline;
                        }
    
    Action:
    public ActionResult Index(string arananKelime)
    {
    return View(Tuple.Create(new videovideoarchive(), new sp_VideoArama_Result()));
    }
    
    • Gençay dedi ki:

      Merhaba Gökhan Bey,
      Modelinizi aşağıdaki örnekte olduğu gibi tam belirtmeniz gerekmektedir.

      @model Tuple<int, SqlConnection>
      

      Bu bir örnek. Siz modelinize uygun Tuple nesnesinin generic referansını oluşturmalısınız.
      Sevgiler.

      • gökhan aydın dedi ki:

        Yazmıştım ama burada gözükmemiş sanırım view tarafında

        model Tuple
        bu şekilde

        • gökhan aydın dedi ki:

          kodu tam gönderemiyorum. engelleme var sanırım.
          @model Tuple videovideoarchive, sp_VideoArama_Result

  5. Onur dedi ki:

    Merhaba,
    Faydalı bilgi için teşekkürler lakin aklıma takılan bir soru var,
    Benim yazdığım 180 tabloluk bir proje var(Şu an için 180) sanırım anladınız 🙂 8 tablodan sonra patladım diyelim, projeyi geri dönüştürmek acaba bana neye mal olur?

  6. Mustafa dedi ki:

    hocam bunları aynen yaptım ama ilişkili verilerde kaydım gelmiyor.Foreign key verileri gelmiyor.

    • Gençay dedi ki:

      Merhaba,

      Foreign key verilerinin gelmesi için Lazy Loading mekanizmasını kullanmanız yahut Include fonksiyonuyla ilişkisel verileri çağırmanız gerekmektedir.

      • Mustafa acar dedi ki:

        Hocam verileri ınclude ettim ama bir türlü verileri alamıyorum.Ben foreign keyleri viewbag ile tanımladım.Burdaki post controllerındaki “model1 “i add yapıyorum sadece textbox verileri geliyor.Diğer türlü tabloyu add yaptığım zaman sadece foreign key verileri geliyor.
        LAZY LOADİNG mekanizmasından da birşey anlamadım

                [HttpPost,
                  ValidateAntiForgeryToken]
                public ActionResult Index([Bind(Prefix = "Item1")] VeterinaryServices Model1, [Bind(Prefix = "Item2")] About Model2, [Bind(Include = "VeterinaryServiceId,AnimalId,HourId,Name,LastName,AnimalNumberId,Date,MainteanceName,MainteanceLastName,MainteanceStartDate,MainteanceEndDate,RegisterDate,IsActive")]VeterinaryServices veterinaryServices)
                {
                    if (ModelState.IsValid)
                    {
                        
                        Model1.RegisterDate = DateTime.Now;
                        db.VeterinaryServices.Add(Model1);
                        db.SaveChanges();
                        return RedirectToAction("Index");
                    }
                    ViewBag.AnimalId = new SelectList(db.Animals, "AnimalId", "Name", Model1.AnimalId);
                    ViewBag.HourId = new SelectList(db.Hours, "HourId", "Hour", Model1.HourId);
                    ViewBag.AnimalNumberId = new SelectList(db.AnimalNumbers, "AnimalNumberId", "Number", Model1.AnimalNumberId);
                    return View();
                }
        
  7. doğukan dedi ki:

    Hocam merhaba MVC sürekli yenilendiğinden dolayı sormak istedim. bu mantık hala çalışıyor mu ?

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir