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

MVC 4.0 Layout Sayfası

Asp.NET Web Form platformunda sayfa tasarımı için kullandığımız Master Page yapıları, projemizde ki diğer .aspx sayfaları için tasarım karmaşıklığına engel olmakla birlikte işimizi oldukça kolaylaştırmaktadır.Mevzu Asp.NET MVC Razor View Engine olayına gelince, Web Formlarda ki Master Page yapısına benzer “_Layout.cshtml” sayfalarını kullanmaktayız.Bu makalemiz de, Layout sayfasıyla ilgili teferruatları inceleyeceğiz.

MVC Razor View Engine mimarisinde çalışırken, sayfa tasarımımızı ister her sayfa da teker teker hazırlayabiliriz, istersekte Layout sayfasında tek seferlik hazırlayarak, sayfalarımızı Layout şablonundan türetebiliriz.

Şimdi bir MVC 4.0 Razor projesi oluşturalım ve konumuzu oradan irdelemeye devam edelim.

Visual Studio derleyicisinden, oluşturduğumuz projenin Solution Explorer penceresine göz atarsak eğer, Model – View – Controller katmanlarını göreceksiniz.(MVC mimarisinin çalışma yapısına önceki MVC 2.0 versiyonuyla irdelediğimiz yazılarımda değinmiştim.)

Aşağıdaki ekran görüntüsünü incelerseniz eğer, View katmanı altında ki “Shared” klasörü içinde “_Layout.cshtml” isimli bir Layout sayfamız mevcut.
MVC40RazorSolution

Bu dosyamız MVC projemiz de kullanacağımız Layout sayfamızdır.İçeriğini incelemeden önce yukarıda ki görüntüde gördüğünüz View katmanı altındaki “_ViewStart.cshtml” isimli dosyadan bahsetmek istiyorum.

Bu dosya, web projemizin View katmanı içinde bulunan bütün .cshtml sayfalarının aynı Layout sayfasını kullanacağını belirtebiliriz.Sistem otomatik olarak bu dosyada belirtilen Layout dosyasını işaretleyecektir.Şimdi bu dosyanın kodlarını inceleyelim.

---_ViewStart.cshtml---
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

“_ViewStart.cshtml” sayfasının kodları yukarıdan incelerseniz eğer projemizde ki Layout sayfasının “_Layout.cshtml” isimli dosyamız olduğunu göstermektedir.

Şimdi “_Layout.cshtml” sayfamızı inceleyelim.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title - My ASP.NET MVC Application</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    </head>
    <body>
        <header>
            <div class="content-wrapper">
                <div class="float-left">
                    <p class="site-title">@Html.ActionLink("your logo here", "Index", "Home")</p>
                </div>
                <div class="float-right">
                    <section id="login">
                        @Html.Partial("_LoginPartial")
                    </section>
                    <nav>
                        <ul id="menu">
                            <li>@Html.ActionLink("Home", "Index", "Home")</li>
                            <li>@Html.ActionLink("About", "About", "Home")</li>
                            <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                        </ul>
                    </nav>
                </div>
            </div>
        </header>
        <div id="body">
            @RenderSection("featured", required: false)
            <section class="content-wrapper main-content clear-fix">
                @RenderBody()
            </section>
        </div>
        <footer>
            <div class="content-wrapper">
                <div class="float-left">
                    <p>&copy; @DateTime.Now.Year - My ASP.NET MVC Application</p>
                </div>
            </div>
        </footer>
        @Scripts.Render("~/bundles/jquery")
        @RenderSection("scripts", required: false)
    </body>
</html>

“_Layout.cshtml” sayfasının kodlarını yukarıdan inceleyebilirsiniz.Visual Studio 2012 versiyonunda hazır oluşturulan bir MVC projesinin varsayılan olarak gelen tasarım kodları Layout sayfamızda mevcuttur.Burada html kodlarına takılmanıza gerek yok.Burada dikkat etmemiz gereken bir kaç husus ve kural vardır.Şimdi onları inceleyelim..

RenderBody() metodu;
Bu metod teorik olarak Layout sayfamızın temelini teşkil etmektedir.Yani buradaki kastım, bu Layout sayfasından türetilen bir .cshtml sayfasının ilk yayınlanacağı alan varsayılan olarak RenderBody() metodunun bulunduğu alandır.

Örnek olarak projemize bir “Ornek(Controller).cs” adında bir Controller sınıfı ekleyelim.

---OrnekController.cs---
    public class OrnekController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }

Eklediğimiz Controller sınıfımızın içinde varsayılan olarak ActionResult tipinden “Index” isminde metodumuz gelmektedir.Şimdi bu “Index” isimli metodumuzun View katmanında ki sayfasını oluşturalım.Tabi dikkat etmemiz gereken nokta, oluşturacağımız sayfayı “_Layout.cshtml” ismindeki Layout sayfamızdan türevlendirmektir.”_ViewStart.cshtml” isimli dosyamızda Layout sayfamızın yolunu bahsettiğimizden dolayı MasterPage olarak Layout sayfamızı göstermemize gerek yok.Ancak varsayalım ki, “_ViewStart.cshtml” sayfasında Layout sayfamızın yolunu belirtmedik, işte o zaman aşağıdaki kodu View katmanında ki sayfalarımızda kullanabiliriz.

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

Her neyse..Biz konuyu dağıtmayalım.Index metodumuzun View kaymanındaki sayfasını oluşturalım.

@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
Merhaba, bu Index Action'ının View katmanında ki sunumudur.

Gördüğünüz gibi, oluşturmuş olduğumuz “Index.cshtml” sayfasının içini yukarıdaki gibi kodladım.Eğer projemizi derleyip çalıştırırsak eğer, “Ornek(Controller).cs” isimli Controller sınıfımızda ki Index isimli Action tetiklenirse, “Index.cshtml” sayfasının içeriği RenderBody() metodumuzun bulunduğu alanda gösterilecektir.

Eğer ki, Asp.NET Web Form mimarisinde ki Master Page yapısında bulunan “ContentPlaceHolder” nesnesi gibi, tasarımın istediğimiz alanına bölüm eklemek istiyorsak RenderSection() metodu kullanılmalıdır.

RenderSection() metodu;
Bir Layout sayfası içinde bir tane RenderBody() metodu kullanmak zorunludur.Ancak birden fazlada kullanamayız.
Fakat az yukarıda bahsettiğimiz gibi, tasarımımıza bölüm eklemek istiyorsak eğer birden fazla RenderSection() metodunu kullanabiliriz.Şimdi yazımın üst satırlarında bulunan “_Layout.cshtml” isimli Layout dosyasının kodlarını inceleyiniz.Orada göreceğiniz gibi bir kaçtane “RenderSection() metodu kullanılmış.

RenderSection() metodumuzun prototipi aşağıdaki şekildedir.

@RenderSection("Metodun yazıldığı alana bir isim vermiş oluruz.")

RenderSection() metodu sayesinde tasarımımız da ayarladığımız bölümü kullanabilmek için, “section” anahtar sözcüğü kullanılmaktadır.

“Ornek(Controller).cs” isimli Controller sınıfında bulunan Index isimli metodumuzun View dosyasının içeriğini yayınlamak için hiç bir alan belirtmediğimizden dolayı varsayılan olarak RenderBody() metodunun bulunduğu alanda içeriğimiz yayınlanmaya başlandı.Dolayısıyla, ben RenderSection() metodumla seçtiğim alanda içerik yayınlamak istiyorsam aşağıdaki gibi View katmanındaki dosyamızı tazelemem lazım.

@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
@section featured
{
Merhaba, bu Index Action'ının View katmanında ki sunumudur.
    }

Gördüğünüz gibi, RenderSection() metodu ile işaretlenmiş ve “featured” ismi verilmiş alana işlemlerimi yayınladım.Eğer projeyi derleyip çalıştırırsanız RenderBody() metodu değil “featured” isminden seçmiş olduğumuz RenderSection() metodumuzun bulunduğu yerde yayınlama işlemi yapmış olacağım.Bu arada hatırlatma amaçlı söylemekte fayda var diye düşünüyorum, “featured” isim alanına sahip RenderSection() metodu projemizin Layout sayfasında mevcuttur.

Eğer dermanı kalıpta buraya kadar okuyanınız varsa kesinlikle kafanıza aşağıdaki sorun takıldı.
“Bu herif _Layout.cshtml sayfasındaki RenderSection() metodunu yanlış gösterdi.” 🙂

Evet biliyorum.Bu hatayı yaptığımın farkındayım.Çünkü bizzat yazımızın üst satırlarında yazmış olduğum “_Layout.cshtml” sayfasının içinde kullanılan RenderSection() metodu şu şekildeyken,

@RenderSection("featured", required: false)

ben prototipte şu şekilde gösterdim,

@RenderSection("bolumadi")

Hmm..Acaba neden böyle yaptım.Çünkü iki türlüde derleyici hatasız çalışacaktır.Ancak Layout sayfamızda ki RenderSection() metodumuzda neden bölüm adından sonra bir parametre daha varsayılan olarak otomatikman girilmiş diye sorarsanız eğer, View katmanında ki dosyada bulunan “section” anahtar sözcüğüyle işaretlenmiş alanlarımız bulunamazsa program çalışma zamanında hata verecektir.Yani örneklendirirsem, RenderSection(“Ahmet”) diye bir metod tanımlamış olayım Layout sayfamda.Eee haliyle, bu Layout sayfam derlendiğinde, RenderSection metoduna geldiğinde “Ahmet” isminde bir “section” arayacaktır.Eğer bulamazsa da hata verecektir.

İşte Layout sayfasında RenderSection metoduyla işaretlenmiş alanın, View katmanındaki sayfasında “section” ı bulunmadığı zaman hata vermemesi için aşağıdaki gibi kullanılmaktadır.

@RenderSection("alanadi", required: false)

veya

@RenderSection("alanadi", false)

Bir “section” ın olup olmadığını anlamak için “IsSectionDefined” metodu kullanılmalıdır.
Tabi bu makalemizde örnek olarak üzerinde çalıştığımız Layout sayfamızda bu metodla ilgili bir örnek bulunmamaktadır ancak bunuda göstermemde fayda var.

        @{if (IsSectionDefined("ahmet"))
          {
            @RenderSection("ahmet")
          }
          else
          {
              Write("Ahmet isimli section bulunmamaktadır.");
          }
        }

Yukarıdaki kod bloğunu incelerseniz eğer, Layout sayfamızda bir Section çağırırken önceden var mı? yok mu? kontrol ediliyor ve ona göre Render ediliyor.

Son olarak RenderPage() metodundan bahsedelim.
RenderPage() metodu;
RenderPage metodu ile projemizde bulunan herhangi bir View sayfasının içeriğini, kullanıldığı alanda yayınlayabiliriz.

Örnek olarak oluşturduğumuz projemizde “Ornek(Controller).cs” ismindeki Controller sınıfının içine “Sayfa” isminde bir ActionResult tipinden metod tanımlayalım.

    public class OrnekController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
        public ActionResult Sayfa()
        {
            return View();
        }
    }

Bu metodun View katmanında sayfasını oluşturup aşağıdaki gibi düzenleyelim.

@{
    ViewBag.Title = "Sayfa";
}
<h2>Sayfa</h2>
Bu içerik Sayfa Action'ının içeriğidir.

Layout sayfamızda RenderPage metodu ile “Sayfa.cshtml” sayfamızı yayınlayalım.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title - My ASP.NET MVC Application</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <meta name="viewport" content="width=device-width" />
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    <header>
     --- @RenderPage("~/Views/Ornek/Sayfa.cshtml"); ---
        <div class="content-wrapper">
            <div class="float-left">
                <p class="site-title">@Html.ActionLink("your logo here", "Index", "Home")</p>
            </div>
            <div class="float-right">
                <section id="login">
                    @Html.Partial("_LoginPartial")
                </section>
                <nav>
                    <ul id="menu">
                        <li>@Html.ActionLink("Home", "Index", "Home")</li>
                        <li>@Html.ActionLink("About", "About", "Home")</li>
                        <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                    </ul>
                </nav>
            </div>
        </div>
    </header>
    <div id="body">
        @RenderSection("featured", required: false)
        <section class="content-wrapper main-content clear-fix">
            @RenderBody()
        </section>
    </div>
    <footer>
        <div class="content-wrapper">
            <div class="float-left">
                <p>&copy; @DateTime.Now.Year - My ASP.NET MVC Application</p>
            </div>
        </div>
    </footer>
    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
</body>
</html>

Gördüğünüz gibi RenderPage metodu ile “Sayfa.cshtml” sayfamızın içeriğini çağırmış olduk.Şimdi projemizi derleyip çalıştıralım.
mvc40LayoutRenderPage

Bu makalemizde Layout sayfasının kendisi ve metod teferruatını incelediğimizden dolayı, Layout sayfamızda gördüğünüz “@ViewBag.Title”,”@Styles.Render()” gibi kodların ne işe yaradığını bu yazıda açıklamayacağım.Diğer makalelerimde bu kod ve metodlarla ilgili açıklamalarımı görürsünüz.

Sonraki makalelerimiz de görüşmek üzere..
Faydalanmanız dileğiyle..
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

6 Cevaplar

  1. Kutlugalp dedi ki:

    Sağolasın tam @RederBody gibi birşey arıyordum bu konu karşıma çıktı senin sayende @RederSection diye bir şey olduğun öğrendim.

  2. Mehmet Erden dedi ki:

    Şu anda merak ettiğim RenderBody() metodu idi, ama çokta bir şey anlayamadım, render body() metodunda anlatılmak istenen tam ifade edilememiş doğrusu.

    Ama gayret ve çabalarınız için teşekkür ediyorum.

    • Gençay dedi ki:

      Büyük ihtimal RenderBody metodu hakkında internetteki diğer makalelerde araştırma yapıp, göz gezdirdikten sonra bu makaleye denk geldiğinizi düşünüyorum. Ki keza bu konu hakkında ufak bir cümle okuduktan sonra bir diğer makalede ilgili konuya farklı bir yaklaşımda yorum gördüğünüz taktirde anlatacak seviyede anlamanız gerekmektedir. Çünkü merakınız bir metottan ibarettir ve amacınız sadece işlevsel olarak ne işe yaradığını anlamaktır. Yani Allah aşkına bir metod daha ne kadar ifade edilebilir? Sizin için bir metodun, sade ve sadece bir metodun işlevini daha nasıl ve ne kadar ifade etmemiz gerekmektedir? Başlangıç ve orta düzey bir yazılımcının anlayacağı dilin dışında, sizin seviyenize özel hangi dilde konuyu ele almalıyım? Lütfen bu konuda bana yardımcı olursanız tüm okuyucu kitlemi kapsayacak derecede makalelerimi derleyeceğime emin olabilirsiniz…

      Selametle!

  3. dedi ki:

    yazi ucun tesekkurler

  4. selahattin kayacan dedi ki:

    Merhaba,
    benim _layout.cshtml dosyamda bir navigation menüm var. bu menünün item larını db den almam gerekiyor. bunu nasıl yapmalıyım?
    teşekkürler.

  5. Bilal dedi ki:

    Gerçekten en açıklayıcı anlatımlar sizinkiler oluyor. En ince ayrıntısına kadar öğreniyoruz. Çok teşekkürler.

Bir cevap yazın

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