Bu makalemizde .Net MVC ‘nin View katmanını irdeleyip MVC Layout – PartialView – Section kavramları üzerinde duracağız
Layout
Hatırlarsanız önceki makalelerde Abstract sınıflardan bahsetmiştim. Ortak özellikleri taşıyan sınıflardı. Layout’ları da View’ların abstract sınıfı olarak düşünebilirsiniz. Layout ASPNet Web Forms MasterPage yapısının epeyce geliştirilmiş halidir. Örnekle; site tasarımımızda sol tarafta bir menü bar olduğunu varsayalım. 10 adet cshtml view için her sayfada bu menünün kodlanması nasıl olurdu ? Peki yönetimi nasıl olurdu ? cevaplar kötü ve çok kötü olacak 🙂 Layout’lar genel sayfa şablonu oluşturmak için kullanılır. Yukarıda Abstract benzetmesi yapmıştık. Ortak olan özellikleri barındırır demiştik. Peki web deyince hemen aklımıza gelen JQuery – JavaScript dosyalarını her sayfada tanımlayacak mıyız ? Hayır, bunun yerine dosyalarımızı Layout üzerinde tanımlayacağız.Kendisinden türeyen sayfalara aktaracaktır. MVC layout oldukça esnek bir yapıya sahiptir. Layout içinde çeşitli PartialView ,Section ,View çağrısı yapabiliriz.
PartialView
ASPNet UserControl’ü hatırlarsınız. UserControl’ün MVC mimarisindeki karşılığı PartialView ‘dır. Tabiki UserControl’e göre çok daha esnek bir yapıya sahiptir. Tek başına kullanılmaz View sayfalara entegre halde çalışırlar. Kod tekrarlarını engellemek için birebirdir. Nar gibidir yani, çarşıdan aldım 1 tane eve geldim 1000 tane 🙂 Peki nerelerde kullanırız ? Tekrar olabilecek sayfalarda, karmaşık sayfalarda PartialView tercih edebiliriz. Karmaşık yapıdaki sayfaları tümden ele almak yerine küçük parçalar halinde işlemek daha kolay olacaktır ayrıca kod okunabilirliği de artacaktır.
Section
Section kavramı view içerisinde belirli yerleri özelleştirmek istediğimizde öne çıkan bir yapıdır. Bu bir içerik veya script olabilir. Belirli bir bölümde özel bir script’i sayfaya entegre etmektense sadece o kısımda çağrılmasını sağlayabiliriz. Başka bir bakış açısıyla kullandığımız sayfaya kısıtlama getirebiliriz. Örneğin tasarlayacağımız bir sayfada Master-Datail yapısına uygun iki farklı bölüm görmek istiyorsak tanımlayacağımız zorunlu Section‘lar bunu sağlayacaktır. Section kullanılırken required parametresi alır. Default değeri True olarak belirlenmiştir. Bu şekilde tanımlı bir section render edilmezse sayfa hata verir. Değeri false yaparak zorunluluğu ortadan kaldırmış oluruz.
Şimdi örneğimize geçelim. Öncelikle layout tanımımızı yapacağız. Layout tüm sayfaların türetildiği view olacak. Daha sonra kullanıcı girişi yapabileceğimiz bir PartialView olacak. Giriş yapıldıktan sonra kullanıcı bilgilerini session’ da saklayıp Partial Render edildiğinde ekranda göstereceğiz. Section için sayfalarda görünecek bir içerik belirleyeceğiz Son olarak Master-Detail yapısında bir sayfa yapıp section kısıtlamasını örnekleyeceğiz.
Hemen yeni bilisimIO_Layout adında bir proje oluşturuyoruz. Projeyi oluştururken ekrana gelen Template bölümünden MVC yi seçip Change Authentication kısmında yetkilenirmeyi kaldırıyoruz.
Projemiz oluştuktan sonra hali hazırda _Layout.cshtml sayfası oluşturuluyor.
Şimdi sayfa üzerinde bazı değişiklikler yapacağız.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
@using bilisimIO_Layout.Models <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - My ASP.NET Application</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> <li>@Html.ActionLink("Contact", "Contact", "Home")</li> </ul> </div> <div style="float: right; background-color: red"> @Html.Partial("_PartialUserInfo", Session["LoginInfo"] == null ? new UserInfo() : (UserInfo)Session["LoginInfo"]) </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> @RenderSection("OptinalContent",false) <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html> |
Şimdi ekleme yaptığımız kod bloklarını inceleyelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<div style="float: right; background-color: red"> @Html.Partial("_PartialUserInfo", Session["LoginInfo"] == null ? new UserInfo() : (UserInfo)Session["LoginInfo"]) </div> <div class="container body-content"> @RenderBody() <hr /> @RenderSection("OptinalContent",false) <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div> |
@RenderBody()
Bulunduğu yere çağrı yaptığımız sayfalar gelecektir. Controller metotlarımızdan Return edilen View’lar direkt olarak burada render olur. Bu şekilde _Layout.cshtml den türeyen tüm View’lar için değişen kısım sadece burası olacaktır.
@RenderSection
Section için belirli yerlere istediğimiz eklentiyi yapmak için kullanılır demiştik. Bu kod sayesinde herhangi bir View ‘ da OptinalContent section ‘ı tanımlarsak _Layout ‘a render etmiş olacağız. Yukarıda bahsettiğimiz gibi required parametresini false olarak belirledik.Bu şekilde zorunluluğunu ortadan kaldırmış olduk. Section içeriğini aşağıdaki gibi tanımlıyoruz.
1 2 3 4 5 6 7 8 9 10 11 |
// Index.cshtml @section OptinalContent { <div style="background-color: red"> <label> Opsiyonel section tanımı yapıldı. </label> </div> } |
PartialView
1 2 3 4 5 6 7 |
<div style="float: right; background-color: red"> @Html.Partial("_PartialUserInfo", Session["LoginInfo"] == null ? new UserInfo() : (UserInfo)Session["LoginInfo"]) </div> |
PartialView eklemek için Views altında PartialView’ın ekleneceği klasör’e sağ tıklayıp Add > View seçeneğini seçiyoruz. Görseldeki gibi işaretliyoruz.
View’ ı ekledikten sonra kullanacağımız model’i oluşturalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
namespace bilisimIO_Layout.Models { public class UserInfo { /// <summary> /// Kullanıcı No Bilgisini Saklar /// </summary> public int Id { get; set; } /// <summary> /// Kullanıcı Ad bilgisini saklar /// </summary> public string Name { get; set; } /// <summary> /// Kullanıcı SoyAdı bilgisini saklar /// </summary> public string Surname { get; set; } /// <summary> /// Kullanıcı Ad bilgisi /// Siteye giriş için kullanılır /// </summary> public string UserName { get; set; } /// <summary> /// Sifre bilgisini saklar /// Siteye giriş için kullanılır /// </summary> public string Password { get; set; } } } |
PartialView kodlarımızı oluşturuyoruz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
@using bilisimIO_Layout.Models @model bilisimIO_Layout.Models.UserInfo @{ Layout = null; } @if (Model != null && Model.Id > 0) { <label>@Html.DisplayFor(p => p.Name)</label> <label>---</label> <label>@Html.DisplayFor(p => p.Surname) </label> } else { using (Html.BeginForm("UserInfo", "Home", FormMethod.Post, Model)) { <div> @Html.TextBoxFor(p => p.UserName) @Html.PasswordFor(p => p.Password) <input type="submit" name="btnUser" /> </div> } } |
PartialView ‘a düşen model ‘imizi kontrol ediyoruz. Model boş gelirse yada Id değeri 0 dan küçükse veya eşitse kullanıcı giriş bilgilerini ekrana getiriyoruz. Zaten giriş yapmış bir kullanıcı ise PartialView giriş yapan kullanıcı bilgilerini ekrana getiriyor.
Section
Section kullanarak Master-Detail tarzı bir sayfadan bahsetmiştik. Bu sayfa için gerekli kodları ekleyelim.
_Layout.cshtml üzerinden _MasterDetailLayout adında bir View ekliyoruz. view’ı ayrı bir Layout olarak kullanacağız.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@{ ViewBag.Title = "_MasterDetailLayout"; <strong>Layout = "~/Views/Shared/_Layout.cshtml";</strong> } <h2>_MasterDetailLayout</h2> <div id="dvBase" style="height: 500px; width: auto; border: 1px red"> <div id="dvMaster" style="float: left; height: 200px; border: 1px green; padding: 3px"> @RenderSection("MasterContent", true) </div> <div style="clear: both"></div> <div id="dvDetail" style="float: left; height: 300px; border: 1px green; padding: 3px"> @RenderSection("DetailContent", true) </div> </div> |
Yukarıda görüldüğü gibi @RenderSection required parametresi true. Bu sayfanın kullanıldığı yerlerde MasterContent ve DetailContent section ‘ları mutlaka tanımlanmalı. Aksi halde hata alırız.
son olarak MasterDetailLayout ‘ u kullanan bir view daha ekliyoruz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@{ ViewBag.Title = "MasterDetail"; Layout = "~/Views/Shared/_MasterDetailLayout.cshtml"; } <h2>MasterDetail sayfa</h2> @section MasterContent { <label> MasterContent Section içerik </label> } @section DetailContent { <label> DetailContent Section içerik </label> } |
Makalemizin girişinde bahsettiğimiz gibi Layout kullanarak sitemizde bir çatı oluşturduk. PartialView ile kullanıcı girişi ve detay bilgisini layout üzerine entegre ettik. Aynı zamanda istediğimiz sayfalarda belirli içerikleri gösterebilmek için Section kullandık. Yine section ile sayfa kullanımını belirli bir yapıda (Master-Detail) zorunlu hale getirdik.
Umarım faydalı bir yazı olmuştur.
PartialView
Section
Index Sayfasında Section bilgisi oluşturulurken diğer sayfalarda bu bilgi görünmeyecektir.
MasterDetailPage
H.Burak Karadağ
Referance
https://docs.microsoft.com/en-us/aspnet/core/mvc/views/partial
https://msdn.microsoft.com/en-us/library/dd410123(v=vs.98).aspx