ASP.NET Core 5/View'lar ve Controller'dan View'a veri taşıma

View'lar web uygulamalarının kullanıcıya görünen yüzüdür. ASP.NET Core'da view'lar Views klasöründe ve her controller için ayrı klasör olacak şekilde tutulur. Normal şartlar altında her action'a bir view karşılık gelir. View dosyalarının uzantısı cshtml'dir. Bir view dosyası esasında C# kodu içerebilen bir HTML dosyasıdır. İlgili view render edildiğinde view'ın içindeki C# kodları sunucu tarafında çalıştırılır ve kullanıcıya salt HTML gönderilir. View'ın içindeki C# kodları çoğunlukla controller'dan gelen verinin sayfada uygun yere yerleştirilmesi amacıyla kullanılır. View dosyalarında HTML ile C# kodları bir arada aşağıdaki gibi kullanılır:

<html>
    <head>
        <title></title>
    </head>
    <body>
    @{
        int a = 0;
        for(int i=0;i<5;i++)
        {
            a++;
        }
    }
    </body>
</html>

Buradaki C# kodunun pek bir işlevselliği yoktur. Yalnızca HTML içinde C# kodunun çalışabildiğini göstermek için kullanılmıştır. Eğer algoritmik pek bir şey yapmayacaksak, sadece bir değişkenin değerini sayfada ilgili yere yazdıracaksak küme parantezleri açmadan ilgili değişkene @ ön ekini ekleyerek kullanabiliriz. Bu durumda komutun sonlandığını göstermek amacıyla noktalı virgül kullanmayız:

<html>
    <head>
        <title></title>
    </head>
    <body>
    @DateTime.Now.ToString()
    </body>
</html>

Aşağıdaki kodda ise C# kodunun içinde HTML kullanılmıştır:

<html>
    <head>
        <title></title>
    </head>
    <body>
        <ul>
        @{
            for(int i=0;i<5;i++)
            {
                <li>@i</li>
            }
        }
        </ul>
    </body>
</html>

Bu kod 0'dan 4'e kadar olan sayıları, her sayı bir liste ögesi olacak şekilde ekrana basmaktadır. Razor sentaksı çok çetrefilli olabilmektedir. Şimdilik bu konuyu burada bırakalım. İleride Razor sentaksına geri döneceğiz. Şimdilik controller'dan view'a nasıl veri taşıyabileceğimize bakalım.

Controller'dan view'a veri taşıma değiştir

Controller'dan view'a model bazlı, ViewBag ile, ViewData ile ve TempData ile veri taşınabilmektedir.

Model bazlı veri taşıma değiştir

Controller'dan view'a model bazlı veri taşıma şöyle yapılır:

@model List<OrnekUygulama.Models.Urun>
<html>
    <head>
        <title></title>
    </head>
    <body>
        <ul>
        @{
            foreach(var urun in Model)
            {
                <li>@urun.Ad</li>
            }
        }
        </ul>
    </body>
</html>

Burada öncelikle ilk satırda hangi tipte verinin taşınacağı belirtilmiştir. Burada ilgili view dosyasının bir ürün listesi alacağını belirttik. Şimdilik Urun sınıfını isim alanlarıyla belirtmek zorundayız. C# kodunda ise her bir ürünün adını ekrana bastık. C# kodunda modele Model anahtar sözcüğü ile eriştik.

Controller tarafında ise view'a veriyi şöyle gönderdik:

List<Urun> lu = new List<Urun>
{
    new Urun{Id=1,Ad="silgi",Adet=4},
    new Urun{Id=2,Ad="kalem",Adet = 5},
    new Urun{Id=3,Ad="defter",Adet=1}
};
return View(lu);

Yani sadece ilgili View() metoduna modeli parametre verdik.

ViewBag ile veri taşıma değiştir

ViewBag türü dynamic olan bir değişkendir. Dolayısıyla ViewBag'e istediğimiz üye eleman varmış gibi davranabiliriz. View tarafında eğer controller tarafında ViewBag'e eklemlendirilen alanı kullanırsak veriyi de elde etmiş oluruz. Örnek (controller tarafında):

ViewBag.Isim="ahmet";
return View();

View tarafında:

<html>
    <head>
        <title></title>
    </head>
    <body>
        @ViewBag.Isim
    </body>
</html>

ViewData ile veri taşıma değiştir

ViewData yöntemi ViewBag yöntemine benzer. Ancak ViewBag yönteminden farklı olarak sözlük formatındaki bir yapıyla veriyi taşır. Örnek (controller tarafında):

ViewData["isim"]="ahmet";
ViewData["soyad"]="yılmaz";
return View();

View tarafında:

<html>
    <head>
        <title></title>
    </head>
    <body>
        Ad: @ViewData["isim"] <br />
        Soyad: @ViewData["soyad"]
    </body>
</html>

TempData ile veri taşıma değiştir

ViewData ile veri taşımaya çok benzer. Veri yine sözlük formatında taşınır. ViewData ile arasındaki fark ise veriyi cookie'lerle taşımasıdır. Bunun faydası ise bir action direkt view'ını döndürmek yerine akışı başka bir action'a yönlendirdiğinde ortaya çıkar. Diğer veri taşıma yöntemlerinde akış başka bir action'a geçtiğinde gönderilen veriler kaybolur. Halbuki TempData verileri tutmaya devam eder. Örnek (controller tarafı):

public IActionResult Index()
{
    TempData["isim"] = "bekir";
    TempData["soyad"] = "oflaz";
    return RedirectToAction("Index2");
}

public IActionResult Index2()
{
    return View();
}

View tarafı (Index2'nin view'ı):

<html>
    <head>
        <title></title>
    </head>
    <body>
        Ad: @TempData["isim"] <br />
        Soyad: @TempData["soyad"]
    </body>
</html>

TempData'nın diğer veri taşıma yöntemlerine kıyasla zayıf tarafı ise sadece string gibi basit tipleri taşıyabilmesidir. Halbuki model, ViewData ve ViewBag yöntemleriyle karmaşık tipte veriler de taşıyabiliriz.

Karmaşık veriyi TempData ile taşınabilir hale getirme değiştir

Karmaşık veriyi TempData ile taşıyabilmemiz için serileştirmemiz gerekmektedir (controller tarafı):

public IActionResult Index()
{
    List<Urun> lu = new List<Urun>
    {
        new Urun{Id= 1, Name ="defter",Quantity=1},
        new Urun{Id= 2, Name="silgi",Quantity=3},
        new Urun{Id=3,Name="kitap",Quantity=2}
    };
    string data = JsonSerializer.Serialize(lu);
    TempData["data"] = data;
    return RedirectToAction("Index2");
}

public IActionResult Index2()
{
    List<Urun> lu = JsonSerializer.Deserialize<List<Urun>>(TempData["data"].ToString());
    ViewBag.Data = lu;
    return View();
}

Burada Index2 kendi view'ına veriyi ViewBag ile göndermektedir. TempData sayesinde iki action arasında verinin kaybolması önlenmiştir. Bundan sonrası ViewBag ile veri taşıma olduğu için view tarafındaki kodlar gösterilmemiştir.

Veri taşıma yönetmlerinin karşılaştırması değiştir

Diğer veri taşıma yöntemlerine kıyasla model bazlı veri taşıma yöntemi en avantajlısıdır. Çünkü model bazlı veri taşıma iki taraflı olması için tasarlanmıştır. Yani model bazlı veri taşıma ile hem controller'dan view'a, hem de view'dan controller'a veri taşıyabiliriz. Diğer veri taşıma yöntemleri ise yalnızca controller'dan view'a veri taşımak için tasarlanmıştır. Nasıl view'dan controller'a veri taşıyabileceğimiz, diğer bir deyişle nasıl kullanıcıdan veri alabileceğimiz sonraki bölümlerde açıklanacaktır.

Controller'dan view'a Tuple göndermek değiştir

Controller'dan view'a Tuple nesnesi gönderilebilir. Tuple'lar birden fazla nesne tutabilen sınıflardır. Ayrıca C# programlama dili Tuple'lar için özel sektaksa sahiptir. Controller'dan view'a Tuple gönderme (controller tarafı):

 User user = new User { Id=1, Name="Bekir", Surname="Oflaz" };
 Product product = new Product {Id=1, Name="Eraser", Quantity=5 };
 var tuple = (user, product);
 return View(tuple);

View tarafı:

 @model (WebApplication6.Models.User, WebApplication6.Models.Product)
 <html>
     <head></head>
     <body>
         @Model.Item1.Name
         <br />
         @Model.Item2.Name
     </body>
 </html>

Bu örnekte Tuple'ın bileşenleri isimsizdir. Bu durumda Tuple bileşenlerine Item1, Item2, ... diğerek erişebiliriz. İstersek Tuple bileşenlerine isim de verebiliriz:

 @model (WebApplication6.Models.User u, WebApplication6.Models.Product p)
 <html>
     <head></head>
     <body>
         @Model.u.Name
         <br />
         @Model.p.Name
     </body>
 </html>