18 Temmuz 2014 Cuma

MVC Film Uygulaması - View Ekleme (Part II)

Bu yazımızda, istemciye gidecek HTML sayfalarının oluşturulması sürecini daha mimarisel bir hale getireceğiz ve oluşturacağımız view şablonlarımızı kullanmak için MerhabaDunyaController sınıfımızı düzenleyeceğiz. Ama düzenlemeye geçmeden hemen önce isterseniz Empty olan MVC projemize gerekli CSS, script ve bundle'ları ekleyelim. Projemize sağ tıklayıp Add > New Scaffolded Item seçelim:


Çıkan Add Scaffold penceresinde sağ taraftan MVC'yi seçelim ve ortada bulunan MVC 5 Dependencies'i seçelim ve Add'e tıklayalım.


Add MVC Dependencies penceresinden Full Dependencies'i işaretleyelim ve ekleyelim. Bu işlem birkaç saniye alabilir.

Solution Explorer pencerimizde CSS'ler ve scriptler gibi birçok dosyanın eklendiğini görüyoruz. Ama öncelikle açılan readme.txt dosyasındaki talimatları yapalım. Solution Explorer'da alt kısımlarda bulunan Global.asax dosyasını açalım ve Application Start metodunu aşağıdaki şekilde güncelleyelim:
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}    
BundleTable kısmında hata verecektir. Bu yüzden aşağıdaki namespace'i ekleyelim:
using System.Web.Optimization;
Sonra bu namespace'i /Views dizini altındaki web.config dosyasının içerisindeki namespace'lere ekleyelim:
<add namespace="System.Web.Optimization"/>
Şu an gerekli görünüm dosyalarını eklemiş bulunuyoruz.Fakat daha hiçbirini uygulamamızda kullanmadığımız içindoğal olarak şu an etki etmeyeceklerdir. Öncelikle Razor view engine kullanarak view şablon dosyalarını oluşturalım. Razor-temelli view şablonları .cshtml dosya uzantısına sahiptir. Şık bir kodlama sunan Razor, C# kullanarak HTML çıktılarını oluşturulmasını sağlar. View şablonlarını oluştururken daha az karakter kullanarak hızlı ve akıcı bir kod ortamı sunar.

Şu anki controller sınıfımızda Index metodunun döndürdüğü mesaj, gömülü (hard-coded) olarak kodlanmış halde duruyor. Index metodunun geri dönüş tipini ActionResult ve döndürdüğü değeri View nesnesi olarak aşağıdaki şekilde değiştirelim.
public ActionResult Index() 
{ 
    return View(); 
}
Yukarıdaki Index metodu, artık HTML cevabı oluşturmak için bir view şablonu kullanmak zorunda. Controller metodları (action metod da diyebiliriz), string gibi ilkel bir tip değil genellikle bir ActionResult döndürürler.

Bir view oluşturmak için, \Views\MerhabaDunya klasörüne sağ tık yaptıktan sonra Add e tıklayıp devamında MVC 5 View Page with (Layout Razor) seçeneğini seçelim:


Specify Name for Item diyalog kutusunda Index yazıp OK'a tıklayalım.


Select a Layout Page diyaloğunda ise _Layout.cshtml'i seçip OK'a tıklayalım.


Yukarıdaki diyalogda sağ tarafta, Views\Shared klasörü seçilmiştir. Eğer diğer bir klasörde özel bir şablon dosyamız varsa onu da seçebiliriz.

Şu an \Views\HelloWorld\Index.cshtml dosyası oluşturulmuş durumda.



Aşağıdaki sarıyla işaretlenmiş kodu ekleyelim.
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>View şablonumuzdan koca bir merhaba!</p>

Uygulamamızı çalıştıralım ve URL'in sadece localhost:xxxxx kısmı kalacak şekilde bırakalım adrese gidelim:


Tadaa! uygulamız sorunsuz bir şekilde çalışıyor ve eklediğimiz CSS dosyaları da kendini belli ediyor.Aslında şu an MerhabaDunyaController içerisindeki Index metodu çok büyük bir iş yapmıyor. Sadece bu metodun, tarayıcıya cevap olarak bir view döndürmek zorunda olduğunu belirten  return View() satırını çalıştırıyor. Şu an hangi view'ın döndürmesi gerektiğini belirtmedik. Çünkü zaten ASP.NET MVC bizim için \Views\MerhabaDunya klasörü içerisindeki Index.cshtml view'ını varsayılan olarak ayarladı.
Yukarıdaki resimde "View şablonumuzdan koca bir merhaba!" yazısını view içerisine hard-coded olarak yerleştirdik.

Uygulamamız şu an oldiukça hoş görünüyor. Ancak tarayıcıdaki başlığa bakarsak "Index My ASP.NET Appli" yazısını ve sayfanın üzerindeki büyük linkte "Application name" yazdığını görebiliriz. Fakat böyle yazmasını istemiyoruz, bize özel bir uygulama olsun istiyoruz. Bunun için sayfalarımızın görünümünü değiştirmemiz gerekiyor.

View ve Layout Sayfalarının değiştirilmesi

Öncelikle üst taraftaki "Application name" linkini değiştirelim. Bu link uygulamamızdaki her sayfada olmasına rağmen proje içerisinde tek bir yerde kodlanmış halde bulunuyor. Views/Shared klasöründeki _Layout.cshtml dosyasını açalım. Bu sayfa genellikle layout page olarak adlandırılır ve diğer sayfaların kullanması için Shared (paylaşılan) klasörüne konulmuştur.


Layout şablonları tek bir yerden sitemizin HTML içeriğini belirlememizi ve sitemizdeki birçok sayfa için bu içeriği uygulamamızı sağlar. Hadi bir deneme yapalım ve gerçekten bu içeriğin tüm sayfalarda olup olmadığını görelim. 22. satırdaki <ul class="nav navbar-nav"> etiketinin içeriğini aşağıdaki şekilde değiştirelim:
<ul class="nav navbar-nav">
    <li>@Html.ActionLink("Anasayfa", "Index", "MerhabaDunya")</li>
    <li>@Html.ActionLink("Hoşgeldiniz", "Hosgeldiniz", "MerhabaDunya")</li>
    <li>@Html.ActionLink("Hakkında", "Hakkinda", "MerhabaDunya")</li>
</ul>
ActionLink'lerin içeriğinin gösterdiği değerler aşağıdaki şekildedir:

Link Action Metodu (Çalıştırılacak View) Controller Adı
Anasayfa Index MerhabaDunya
Hoşgeldiniz Hosgeldiniz MerhabaDunya
Hakkında Hakkinda MerhabaDunya

Uygulamamızı tekrar çalıştıralım:


Tarayıcı penceremizin boyutu eğer küçükse üst köşede 3 tane alt alta çizgi görebiliriz. Buna tıklarsak eklediğimiz linkler açığa çıkacaktır.
  • Anasayfa linki, şu anki sayfaya bizi yönlendirecektir. 
  • Hoşgeldiniz linki, önceki yazımızda oluşturduğumuz Hosgeldiniz fonksiyonuna götürecektir.
  • Hakkında linki ise, şu an Hakkinda adında bir action metodumuz olmadığı için hata verecektir.

29.satırdaki @RenderBody'e gelelim. RenderBody, tüm view içerikli sayfaların oluşturulmasını ve bir layout sayfası şeklinde paketlenmesini sağlayan bir yer tutucudur.

Uygulamamızdaki Title elemanının içeriğini değiştirmemiz gerekiyor. 19. satıra gelelim. ActionLink'teki "Application Name"'i "MVC Film" olacak şekilde ve Home controller'ını Filmler olacak şekilde değiştirelim. Değiştirilmiş hali aşağıdaki gibi olmalıdır:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Film Uygulaması</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("MVC Film", "Index", "Filmler", null, 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>
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

Uygulamayı çalıştırdığımızda "MVC Film" yazdığını göreceğiz. Bir kere layout şablonunda değişiklik yaptık ve  artık sitemizdeki tüm sayfalarda yeni başlık yer alacak.

Views\MerhabaDunya\Index.cshtml dosyasını ilk kez oluşturduğumuzda aşağıdaki kodu içeriyordu.
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}
Yukarıdaki Razor kodu, layout sayfasının ne olduğunu bize belirtiyor. Views\_ViewStart.cshtml dosyasına bakarsak da aynı Razor kodunu görüyoruz. Views\_ViewStart.cshtml dosyası tüm view'ların kullanacağı genel bir layout oluşturur. Bu yüzden Views\HelloWorld\Index.cshtml dosyasındaki kodu yorum satırı haline getirebiliriz:

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

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>
Layout özelliğini kullanarak farklı bir layout atayabilir veya hiçbir layout kullanılmaması için null olarak ayarlayabiliriz.

Index view'ı içerisindeki title'ı değiştirelim. \Views\MerhabaDunya\Index.cshtml'i açalım. İki tane yerde değişiklik yapacağız: ilki tarayıcıda görünecek olan title kısmı, diğeri ise başlık kısmı (<h2> elemanı). Bunları biraz birbirinden farklı yapalım ki hangi kodu nereyi değiştirdiğini görelim.
@{
    ViewBag.Title = "Film Listesi";
}

<h2>Benim Film Listem</h2>

<p>View şablonumuzdan koca bir merhaba!</p>
Üstteki kod, görüntülenecek HTML başlığını değiştirmek için, Index.cshtml'de yer alan Viewbag nesnesinin Title özelliğini güncelliyor. Layout şablonumuzun, daha önceden değiştirdiğimiz <title> elemanı içerisindeki kısmını kullandığını kolaylıkla görebiliriz.
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Film Uygulaması</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
ViewBag'i kullanarak view şablonu ile layout dosyamız arasında parametreleri kolayca geçirebiliriz.


Uygulamayı çalıştıralım. Tarayıcıdaki başlığın, birincil ve ikincil başlıkların değiştiğini görüyoruz (Eğer tarayıcımızda bu değişiklikleri göremiyorsak, büyük ihtimalle ön belleklenmiş içeriği görüyoruzdur. Ctrl ve F5 tuşlarına birlikte basarak tarayıcımızın sunucudan sayfayı yüklemesini söyleyebiliriz.) Index.cshtml dosyasında değişiklik yaptığımız tarayıcı başlığına bir de ek olarak "- Film Uygulaması" kısmı şablon dosyamızdan eklenmiş durumda.

Ayrıca Index.cshtml view şablonu ile _Layout.cshtml view şablonunun tek bir HTML sayfası geri döndürecek şekilde birleştiğini görüyoruz. Layout şablonları, uygulamamız tüm sayfalarda değişiklik yapmak için gerçekten bir biçilmiş kaftan.

"View şablonumuzdan koca bir merhaba" mesajı ise hard-coded halde duruyor. Şu an MVC uygulamamızın V (View) ve C'si var ama henüz M'si yok.

Verilerin Controller'dan View'a Geçirilmesi

Veritabanı ve modellerden bahsetmeden önce, controller'dan view'a bilgilerin nasıl aktarıldığına bakalım. Contoller sınıfları, gelen URL isteği ile çalışmak üzere tasarlanmışlardır. Bildiğimiz gibi controller sınıfları, gelen tarayıcı isteklerini aldığımız, veritabanından ilgili verileri topladığınız ve son olarak da tarayıcıya nasıl bir cevap türü göndereceğimizi kodladığımız yerdir. View şablonları bir controller tarafından tarayıcıya döndürülecek HTML verisinin oluşturulması ve biçimlendirilmesi için kullanılabilir.

Controller'lar, tarayıcıya iletilecek verilerin view template'lere aktarılmasından  sorumludurlar. Bir view şablonu asla direkt olarak veritabanı ile ilişkide bulunmaz veya uygulamanın business logic kısmıyla ilgilenmez. Bunun yerine view şablonu, sadece controller tarafından kendisine sunulan veriler üzerinde çalışır. Her birimin ilgilendiği bölgenin birbirinden ayrılması ile kodlarımız düzenli, test edilebilir ve daha fazla bakım yapılabilir hale gelir.

Projemizde MerhabaDunyaController sınıfında bulunan Hosgeldiniz action metodu,  isim ve sayi parametrelerini alıyor ve tarayıcıya direkt olarak gönderiyor. Controller'ın, bu cevabı string olarak işlemesi yerine, view şablonunu kullanmasını sağlayalım. Bu sayede view şablonu, cevabı oluşturmak amacıyla controller'dan uygun veri bitlerini view'a geçirmemizi gerektiren dinamik cevabı oluşturacaktır. Bunu, controller'ımızın içerisindeki view şablonunun ihtiyaç duyduğu ViewBag nesnesine dinamik verileri (parametreleri) koyarak gerçekleştirebiliriz. Böylece view şablonu ihtiyaç duyduğu verilere ViewBag'den erişebilir.

MerhabaDunyaController.cs dosyamıza geri dönelim ve Hoşgeldiniz metodunun içeriğini, ViewBag nesnesininne Mesaj ve Sayi parametrelerini ekleyecek şekilde değiştirelim. ViewBag dinamik bir nesnedir. Yani içine istediğimiz şeyi atabiliriz. Çünkü ViewBag nesnesinin belirlenmiş özellikleri yoktur. ASP.NET MVC Model Binding System otomatik olarak adres çubuğuna yazdığımız URL'den, isim ve sayi parametrelerini, metodumuz içerisindeki parametreler ile eşler. MerhabaDunyaController.cs dosyamızın son hali şu şekilde olmalıdır.

using System.Web;
using System.Web.Mvc;

namespace MVCFilm.Controllers
{
    public class HelloWorldController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Hosgeldiniz(string isim, int sayi= 1)
        {
            ViewBag.Mesaj = "Merhaba " + isim;
            ViewBag.Sayi= sayi;

            return View();
        }
    }
}

Artık ViewBag nesnesinin içerdiği veriler, view'a otomatik olarak aktarılacak. Şimdi Hoşgeldin view şablonunu oluşturmaya hazırız. Ama önce Build menüsüne gelip, Build Solution'ı seçerek projenin derlenebildiğinden emin olalım. Şimdi Views\MerhabaDunya klasörüne sağ tıklayıp Add'e tıkladıktan sonra MVC 5 View Page with (Layout Razor)'ı seçelim.


Specify Name for Item diyalog kutucuğunda Hosgeldiniz yazalım ve OK'a tıklayalım.



Select a Layout Page diyalog penceresinde varsayılan olarak gelen _Layout.cshtml'i seçelim ve OK'a tıklayalım.


\Views\MerhabaDunya\Hosgeldiniz.cshtml dosyasını oluşturduk. Bu dosya içerisindeki kodları, kullanıcının girdiği sayıda "Merhaba" diyecek şekilde değiştirelim:

@{
    ViewBag.Title = "Welcome";
}

<h2>Welcome</h2>

<ul>
    @for (int i = 0; i < ViewBag.Sayi; i++)
    {
        <li>@ViewBag.Mesaj</li>
    }
</ul>

Uygulamayı çalıştıralım ve URL'in sonuna şunu ekleyelim:
/MerhabaDunya/Hosgeldiniz?isim=Zafer&sayi=4


URL'den gelen veriler model binder kullanılarak controller'a aktarıldı. Controller, verileri ViewBag nesnesi halinde paketledi ve bu nesneyi view'a iletti. Devamında view HTML olarak verileri görüntüledi.

 Yukarıdaki örnekte ViewBag objesini kullanarak controller'dan view'a veri akışını sağladık. Sonraki yazılarımızda veri aktarımı için view modeli kullanacağız. Verileri aktarmak için view modeli yaklaşımı genellikle view bag'e göre daha çok tercih edilir.

 Sonuçta örneğimiz bir M (model) teşkil etti, fakat veritabanı kullanmadık. Sonraki yazımızda veritabanı kullanarak bir model nasıl oluşturulur onu göreceğiz.


Kaynaklar: ASP.NET

Hiç yorum yok:

Yorum Gönder