Home > ASP.NET | MVC > ASP.NET MVC ve Razor’a Giriş

ASP.NET MVC ve Razor’a Giriş

Posted on 07 Ağustos 2011 | 12 Yorum

Aslında ben web programlamada php‘yi tercih eden birisiyim. Her ne kadar diğer dillerde de siteler yapmış olsam da php benim için hep ilk tercih olmuştur. Nedendir bilemiyorum ama diğer ortamlarda ve dillerde her zaman bir bahane bulmuşumdur, o ortamı ya da dili kullanmamak için… Bazen barındırdığı kısıtlı nesne tabanlı programalama özelliklerinden dolayı php’ye kızıp ASP.NET ya da java‘ya geçmeye çalıştığım olmuştur da. Ama yine dönüp dolaşıp kapağı php’ye atmışımdır. Özellikle asp.net, benim en fazla git gel yaptığım ortamlardan birisidir. O kadar özellik barındırmasına rağmen neden asp.net’e ısınanamıştım? Aslında cevabı çok basit: Web Forms.

Yakın zamanda, benim bu tarz çekincelerimin olduğunu bilen, asp.net kullanan bir dostum beni MVC ve Razor ile tanıştırdı. Ve açıkcası çok etkilendiğimi itiraf ediyorum. Çünkü artık Web Forms gibi hantal olmayan, php’nin esnekliğine sahip olan ve üstelik c# gibi nesne tabanlı programlamada sözü geçen bir dili kullanan bir ortam ile tanışmıştım.

Bu yazıda MVC ve Microsoft’un yeni çocuğu Razor görünüm motorunu(view engine) tanıtıp, küçük bir örnek yapacağız

ASP.NET Web Forms’un Nesi Yok ki!?

Aslında kısa cevap olarak, “fazlası” bile var denilebilir. Evet belki de Web Formları ilk zamanlarda çok iyi bir fikirdi. Fakat gerçekte durum biraz daha karışık. Gerçek hayatta Web Formlarını projelerde kullandıkça bazı durumlar ortaya çıkmıştır. Tabi bu durumlar zaman içinde bir çok kullanıcının deneyimi ile ortaya çıkmış eksikliklerdir. Bu eksiklik ya da gereksiz fazlalıkları şu şekilde maddelendirebiliriz:

  • View State Ağırlığı: View State olarak bilinen, istekler arasında durumları muhafaza etme mekanizması, client ve server arasında çok büyük boyutlarda veri transferine sebep oluyor. Bu veri boyutu, mütevazi bir sitede bile yüzlerce kilobayta varabiliyor. Üstelik bu veri, gönderilmekle kalmıyor tekrar geri geliyor ve her istekte veri iletimindeki miktar katlanarak büyüyor. Bu server üzerindeki bandwidth kullanımını artırdığı gibi, sitenin yavaş tepkilerinden dolayı site ziyaretçilerinin sinirlerinin bozulmasına da sebebiyet veriyor.
  • Sayfa Yaşam Döngüsü: Sayfa yaşam döngüsünün önemli bir parçası olan, client yani istemci tarafındaki event‘lar(olaylar) ile server tarafındaki event handler kodları arasındaki iletişim, aşırı derecede kompleks, karışık ve bir o kadar da narin, çıt kırıldım olabiliyor. Çok az geliştirici View State hataları olmadan çalışma zamanında bileşenlerin(kontrollerin) üzerinde düzgün bir şekilde değişiklik yapabiliyor ya da çok az geliştirici gizemli bir şekilde çalışmayan event handler‘ları farkedebiliyor.
  • Kod Ayrımı Hakkındaki Yanlış Düşünceler: ASP.NET’in code-behind modeli, HTML kodları ile uygulama kodlarını farklı bir dosyada ayırmaya yarıyor. Sunum kısmı ile uygulama kod kısmını ayırdığı için bu model, oldukça alkış getirdi ve takdir gördü. Fakat gerçekte, geliştiriciler sunum kodları(server kontrollerini değiştirmek gibi..) ile uygulama mantık kodlarını(veritabanını kodları gibi…) bu korkunç code-behind sınıflarında birleştirmeye başladılar. Bu da çoğu zaman manasız ve narin, kolay bozulan bir sonuca dönüşmesine yol açmıştır ve açmaktadır.
  • HTML Üzerinde Kısıtlı Kontrol: Server kontrolleri kendilerini HTML olarak render ederler yani bize sonuç HTML kodları olarak gelir. Fakat bu çoğu zaman sizin istediğiniz HTML kodundan gereksiz bir çok kod barındırır. ASP.NET 4′den önce genellikle bu çıktı kodu, web standartlarına uygun değildi veya bunlar üzerinde iyi bir CSS kullanımını zorlaştırıyordu. Ayrıca server kontrolleri Javascript tarafından ulaşılması zor olan, tahmin edilmesi zor ve karışık ID değerleri üretiyorlardı. Her ne kadar ASP.Net 4 ile bu problemler azaltılmışsa da beklediğiniz HTML’yi elde etmeniz halen sıkıntılı olabiliyor.
  • Zayıf Soyutlama: Web Formları mümkün olduğunca HTML’yi sizden gizlemeye çalışır. Yeni ve özel bir davranışı tanımlamaya çalıştığınızda, genellikle bu soyutlamayı bozarsınız. Ki bu sizi postback event mekanizmasında ters mühendislik metodları kullanmanızı ya da istediğiniz HTML’yi elde etmek için duygusuz ve absürd kodlar yazmanıza sebep olur. Ben buna amele mantığı kod yazmak diyorum :) . Ek olarak tüm bu soyutlama hadisesi, işin ehli web geliştiricileri için sinir bozucu bir engelden öteye gidememektedir.
  • Düşük Test Edilebilirlik: Her ne kadar unit-test yani otomatikleştirilmiş testlere ilgim olmasa da, unit-test kullanan geliştiriciler için Web Formları bir çileden ibaret olmuştur. Web Formlarının bu kapalı hali unit testi için uygunsuz bir durum teşkil etmektedir Projeye unit-test dahil etmenin zorluğu da cabası…

Her ne kadar ASP.NET 4 ile burada bahsedilen bazı problemlere çözüm getirilmeye çalışılmışsa da halen çoğu kısıtlamalar ve eksikliker aynen durumunu muhafaza etmektedir.

Model, View, Controller

MVC başlıca şu üç ana daldan oluşan bir yazılım geliştirme tekniğidir:

  • Model: İletimde kullanılan ya da veritabanı gibi ortamlarda kullanılan veriyi ifade eden basit sınıflardır. Web programlamada bu genelde formun POST verileri ya da veritabanındaki bir tabloyu ifade eden bir sınıf olabilir. Sonuçta View ve Controller arasında veri iletimini Modeller ile gerçekleştirmekteyiz.
  • View: Sunum kısmıdır. Yani bu web prgramlama için html sayfasıdır. Razor söz konusu olduğunda dosya uzantısı “.cshtml” dir. Eğer Aspx görünüm motoru kullanılıyorsa bu uzantı “.aspx” olacaktır. Görünüm motorları(View Engine) ve Razor hakkında ileride daha genişçe bahsedeceğiz.
  • Controller: Esas iş gören uygulama kodlarıdır. Mesela bu, form verilerini veritabanına ekleyen bir sınıf olabilir. Sonuçta view katmanının kullanıcıya gösterilmesi için gerekli işlemleri controller gerçekleştirecektir.

Sizi çok terim ile boğmak istemiyorum. Daha fazla bilgi edinmek isterseniz burayı ziyaret edebilirisiniz.

Bir iletişim sayfasını gözümüzün önüne getirelim. Ne vardır basit bir iletişim sayfasında? Ad soyad, e-posta gibi bilgilerin girildiği bir textbox, mesajın yazılacağı bir textarea ve mesajın gönderileceği bir submit düğmesi. Submit düğmesine tıkladığınız anda, form post edilir ve gerekli kontroller yapılarak e-posta gönderilir ya da kullanıcıya hata verilir. MVC mantığı ile düşündüğümüzde, içinde textbox, textarea, button bulunduran sayfamız View katmanıdır. Form post olduktan sonra gelen verilerin uygunluğunu test eden ve e-postanın gönderimini sağlayan kısım ise Controller‘dır. Model ise bu iki katman arasında gelip giden form’un post verilerinin şablonudur. Bu örnek için textboxlardaki ad soyad ve e-posta bilgileri ve textarea’daki mesaj verisi Model ile ifade edilir.

Model ve Controller “.cs” uzantılı bir dosyada bulunan sınıflardan ibaretken View “.cshtml” uzantılı c# ve html kodlarının karışık olduğu bir dosyadır. Bu uzantıların C#’a ait uzantılar olduğunu ifade etmek istiyorum. Eğer Vb.Net kullanıyorsanız bu uzantılar “.vb” ve “.vbhtml” olacaktır. Veya Razor yerine başka bir görünüm motoru kullanıyorsanız “.cshtml” uzantısı değişiklik gösterecektir.

MVC aslında yeni bir teknoloji olmadığı gibi mucidi Microsoft da değildir. MVC, kökleri 1978 yılına dayanan ve Xerox PARC da Smalltalk projelerinde kullanılmış bir yöntemdir. Fakat günümüzde web programlamada ciddi ölçüde popülerlik kazanmıştır. Özellikle Ruby on Rails ile bu had safhaya ulaşmıştır. Ruby on Rails‘in bu popülerliği o kadar artmıştır ki Microsoft’un gözünü açmasına sebep olmuştur. Ruby on Rails‘in bu başarısını, kullandığı dilden çok, içine monte edilen MVC ve ORM mimarilerine bağlamak gerekir. Microsoft sadece MVC’ye el atmamış, ayrıca bir ORM mimarisi olan Entity Framework ve beraberinde LINQ de .NET’e dahil olmuştur. Evet ORM’nin ünlü olmasına sebep LINQ ve Entity Framework değildir aslında.

Şu an için bir çok dilde MVC yapısını kullanan kütüphaneler mevcuttur. Mesela php’de CakePhp, Symfony ve Mojavi MVC kütüphanelerine en güzel örneklerdendir. Fakat bulabileceğiniz çoğu MVC kütüphanesi Rails’den esinlenmiştir.

Belki şu an için kafanızda MVC ne olduğuna dair somut bir fikir oluşmamış olabilir. Makelenin sonununda vereceğimiz küçük örneği kendiniz yaparak somut fikir edineceğinizi tahmin ediyorum.

ASP.NET MVC

MVC mimarisi, Web Forms mimarisinden farklı bir yapıya sahiptir. Web Formlarında tut-taşı mantığı ile çok hızlı bir şekilde siteler oluşturabilirsiniz. Fakat iş yukarıda da bahsettiğimiz gibi özelleştirmeye ve temiz html kodlarına geldiğinde, durum biraz değişiyor. ASP.NET MVC, temiz, standartlara uyumlu html kodları üretmenin farkındadır. Ve barındırdığı Html yardımcı metodları, Web Formların aksine, ciddi ölçüde temiz ve standart uyumlu kodlar üretirler. Küçük bir kontrol için bile bir çok hantal ve karışık kodlar üretmek yerine, CSS ile şekillendirilmiş gayet basit ve hoş kodlar üretir.

Hemen akla gelen, Web Formlarındaki gibi, kodları hazır, menü ve tarih seçici gibi bileşenleri olsa iyi olmazmıydı. Bunun için en iyi çözüm jQuery gibi javascript bileşenleri olacaktır. İşin gerçeği Web Formları kullanırken bile Web Formlarının varsayılan bileşenleri yerine bu tarz bileşenleri daha fazla kullanmaktayız. Bununla birlikte ASP.NET MVC dahili jQuery desteğine sahiptir. Eğer bir fikir edinmek isterseniz buraya göz atabilirsiniz.

Web Formlarının aksine, ASP.NET MVC ile üretilmiş sayfalar View State namına hiç bir veri içermezler. Bu yüzden küçük bir site için bile yüzlerce kilobayt boyutunda olan bu hantallıktan kurtulmuş olursunuz.

Ayrıca ASP.NET MVC mükemmel bir yönelendirme sistemine sahiptir. Bu sayede şu şekildeki bir urlyi:

/web_motoru/Makaleler/Default.aspx?islem=goster&makale_id=41567&sayfa=1

daha temiz ve kullanıcılar için ve seo için daha uygun bir şekle zahmetsizce çevirebilirsiniz:

/makale/mvc-ve-razor/sayfa-1

Böylesine bir yapı hem SEO için hem kullanıcılar için hem de güvenlik için daha kullanışlı olacaktır.

Bunun dışında söyleyebileceğim başka bir şey de, ASP.NET MVC’nin açık kaynak kodlu olduğudur. Bunun bize getirdiği en büyük faydalardan biri şüphesiz debug aşamasında ortaya çıkmaktadır. Sistem bileşenlerinin nasıl çalıştığını görebileceğiniz gibi geliştiricilerin yorumlarını bile kodlarda görebilirsiniz.

Başka bir şey ise, MVC stateless dediğimiz bir yapıya sahiptir. Yani Web Formlarında olduğu gibi sayfanın o anki durumu kayıt altında tutulmaz. Tersine bu yapıya tamamen karşı bir yapıya sahiptir. Bu yüzdendir ki önceden bahsettiğimiz gibi View State’e ihtiyaç duymaz ve kullanmaz.

Razor

Microsoft sadece MVC ve ORM mimarilerini ASP.NET ortamına taşımakla kalmamış yeni bir görünüm motoru da kazandırmıştır. Görünüm Motoru(View Engine), uygulama kodları ile(bu makale için C#), html ve benzeri text tabanlı verileri iç içe kullanmanızı sağlar. ASP.NET MVC için tanımlanmış bir çok görünüm motoru bulunmaktadır. Bunların başlıcaları, Spark, SharpTiles, NHaml, WebForms(ASPX) ve Razor.

Kısacası; Spark, html benzeri bir gramere, SharpTiles java kullanıcılarına yakın bir gramere ve NHaml ise Rail benzeri bir gramere sahip. WebForms ise bildiğimiz ASPX görünüm motorudur. Tüm kodlar <% ve %> işaretleri arasına yazılır.

Razor, Microsoft tarafından geliştirilmiş olan yep yeni bir gramere sahip bir görünüm motorudur. Yeni gramer derken sakın korkmayın. Çünkü Razor diğer görünüm motorlarında olduğu gibi sizi yeni bir grameri öğrenmek zorunda bırakmaz. Kullanacağınız dil yine C# gibi bir .net dili olacaktır. Kısaca Razor:

  • Az yer kaplayan, kompakt, anlamlı ve akıcı bir yapıya sahiptir.
  • Öğrenmesi çok kolaydır.
  • Sizi yeni bir dil öğrenmek zorunluğundan kurtarır.
  • Çok çok iyi bir Intellisense desteği mevcuttur.
  • Unit-test’lerine uygun bir yapısı mevcuttur.

Mesela aşağıdaki ASPX görünüm motoru ile oluşturulmuş kodlara bakalım:

<ul>
<% foreach (var country in Model)
   { %>
        <li><%: country.GetCountryCode(); %></li>
<% } %>
</ul>

Bu kodların Razor karşılığı ise şöyle olacaktır:

<ul>
@foreach (var country in Model)
{
    <li>@country.GetCountryCode()</li>
}
</ul>

Bilmiyorum farkettiniz mi ama C# kodu yazmak için sadece “@” işaretini kullandık. Gördüğünüz gibi çok sade bir grameri var. İlerledikçe bu gramere aşina olacaksınız ama bir kaç küçük detaya değinmek istiyorum.

Yukarıdaki küçük örnekte gördüğünüz gibi basit bir Razor kodunu şu şekilde yazıyoruz:

<div>İsminiz: @Model.Name</div>

“@” işareti ile başlayan inline kodunu herhangi bir şey ile kapatmıyoruz. Bir nesnenin ya da strict sınıfın bir özelliğini ya da metodunu html kodumuz içine yazdırmak istiyorsak bu tarz kullanımı tercih edebiliriz. Gördüğünüz gibi @ ile başlayan kod bloğu, “;” veya “%>” gibi herhangi bir sonlandırıcıya ihtiyaç duymadan, bir satır sonlandırıcısı, bir text ya da html tag’ında sonlanıyor.

Razor daha karmaşık kod bloklarının da benzer bir şekilde üstesinden gelir. Mesela bir if bloğunu ele alalım:

@if (Model.WebSiteName == "Diyezon")
{
    <div>@Model.WebSiteName sitesinin adresi: <a href="@Model.WebSiteUrl">@Model.WebSiteUrl</a></div>
}

Razor süslü parentez ile başlayıp ve biten bu bloğun içeriğini C# kodu olarak kabul eder. Tabiki Razor sahip olduğu akıllı gramer sayesinde blok içinde <div> ile başlayan satırı C# kodu olmadığını anlar ve o satırı html ya da text satırı olarak algılar. Bu satır <div> ile başladığı için içine yerleştireceğimiz tüm C# kodları da @ işareti ile başlamalıdır.

Yukarıdaki örnekte gördüğünüz gibi birden fazla kod satırı eklemek istediğimiz durumlarda kod bloklarını kullanabiliriz. Yani:

@{
    string BirString = "Bu bir string";
    int sayi = 5;
}

Bir kod bloğunun bir satırının ilk terimi bir önceki örnekte olduğu gibi bir html tag’ı ise(bir önceki örnekte <div> idi), Razor bu satırı text ya da html satırı olarak algılar. Fakat bu son örnekte olduğu gibi normal bir karakter ile başlarsa, Razor bu satırı c# kod satırı olarak algılar. Bu yüzden satırı “;” ile sonlandırdık. Çünkü bu satır c# kod satırı.

Peki kod bloğu içinde html tag’i olmadan düz bir yazıyı nasıl yazarız?

<p>
@{
    @:Normal bir yazı satırı<br />
    <text>Normal bir yazı
          satırı daha. Ama bu sefer
          tek satır değil.</text>
}
</p>

Yukarıda iki yöntem ile de bir kod bloğu içinde yazı yazabiliriz. Yukarıdaki örnekte ikinci satırın “<text>” tagı ile başladığına dikkat edin. Bu tag bir html tag’ı gibi gözükse de Razor’a ait özel bir tag’dır. Ve bu tag kaynak kodda gözükmeyecektir. Yani yukarıdaki örneğin html çıktısı aşağıdaki gibi olacaktır:

<p>
Normal bir yazı satırı<br />
Normal bir yazı
satırı daha. Ama bu sefer
tek satır değil.
</p>

Gördüğünüz gibi <text> tagı çıktıda gözükmemektedir. Kısacası bir kod bloğunun içinde bir text ya da html satırı açmak istiyorsdak “@:” ya da “<text>” kullanmalıyız. Seçim size kalmış.

Razor görünüm motoru tahmin ettiğimizden daha akıllı davranır. Mesela aşağıdaki gibi yazıyı:

admin@yahoo.com

bir e-posta olarak algılar. Yani “yahoo” sınıfının ya da nesnesinin “com” özelliğini çağırmaz. Veya aşağıdaki gibi bir inline koduna bakalım:

Merhaba @adSoyad. Bu günün tarihi @tarih.

Inline kodların sonundaki “.” işaretine dikkat edin. Razor bunu normal text olarak algılayacak kadar ve bir metod ya da özellik çağıran nokta gibi algılamayacak kadar zekidir.

Daha fazla ayrıntıya girip kafanızı şişirmek istemiyorum. Şimdilik bu kadarlık gramer bilgisi fazlasıyla yeterli. Eğer daha fazla detaya inmek isterseniz şuradaki sitede güzel bir tablo hazırlanmış, müracaat edebilirsiniz.

MVC’ye Hazırlık

Ben şu anda Visual Web Developer 2010 Express sürümünü kullanıyorum. Hem bedava hem de her ihtiyacınızı karşılamakta. Express sürümlerin eksiği unit-test hadisesi ki ben unit-test ile uğraşmayı sevmediğimi söylemiştim zaten. Ama kullandığınız Visual Studio sürümü her ne ise Web Platform Installer ile ASP.NET MVC 3 paketini rahatlıkla kurabilirsiniz. Eğer MVC’nin daha düşük bir veriyonu kurulu ise yine Web Platform Installer ile ASP.NET MVC 3 Tools Update paketini kurmalısınız.

Yine IIS Express ve SQL Server Express versiyonlarını da kurmanızda fayda var. IIS Express kurmanızda fayda var çünkü ASP.NET Development Server IIS’in desteklediği SSL gibi bir çok şeyi desteklemiyor. SQL Server Express de hâkeza eğer veritabanı kullanan bir proje geliştirecekseniz kurmanız gerekenlerden. Bu ikisi de Web Platform Installer ile sorunsuz bir şekilde kurulabilir.

ASP.NET MVC 3 paketini kurduğunuzda Visual Studio(VS) ya da Visual Web Developerda(VWD) yeni proje ekranında ASP.NET MVC 3 Web Application seçeneğini göreceksiniz. Eğer görmüyorsanız ASP.NET MVC 3 Tools Update paketini kurmamışsınız demektir.

Basit Bir Örnek Yapalım

Anlattıklarımızı somut bir şekilde kavrayabilmek için basit bir örnek yapalım. Makalenin başında MVC’yi tarif etmek için verdiğimiz iletişim sayfası örneğini yapmaya çalışalım.

Küçük bir not: Makale boyunca çoğu terimin ingilizce orjinal hallerini kullanmayı tercih ettim ve ediyorum. Çünkü VWD ya da VS’de karşılaşacağımız terimler hep bu şekildedir. Ve bu şekilde alışmanız daha yararlı olacak kanaatindeyim.

  1. VWD ya da VS’yi açalım ve New Project ile yeni proje açalım. Dil olarak “Visual C#”, proje template’i olarak da “ASP.NET MVC 3 Web Application” seçeneğini seçelim. Proje adı olarak “Iletisim” girelim ve pencereyi tamam’a basarak onaylayalım.
  2. Karşımıza gelen pencereden “View engine” olarak Razor seçili olduğuna dikkat edelim. Template olarak ise “Empty” seçelim ve projemizi oluşturalım.

Solution Explorer’a göz attığımızda bir kaç dosya ve klasörün eklendiğini göreceksiniz. Şu an için bunlara yabancı olmamız doğal. Bizim için burada en önemli klasörler Models, Views ve Controllers klasörleridir. Hiç bir şeye dokunmadan F5 ya da menüden Debug=>Start Debugging ile projeyi çalıştıralım. Bir kaç derleme işleminin ardından browser önümüze gelecek ve proje sayfasını bize gösterecek. Fakat göreceğiniz gibi bir HTTP 404 hatası alacaksınız. Bunun nedeni henüz bir controller nesnemiz bulunmamasıdır.

Bir MVC mimarisinde gelen istekler Controller nesneleri tarafından işlenirler. Siz bir sayfayı çağırdığınızda, o url’ye ait controller bu isteği alır ve işler.

Bir controller genelde System.Web.Mvc.Controller sınıfından türeyen basit bir sınıftan ibarettir. Controller içindeki her bir public metoda action method adı verilir. Bu action metodlar web üzerinden herhangi bir url ile çalıştırılırlar. Her ne kadar zorunlu olmasa da oluşturduğumuz controller sınıflarını Controllers klasörü altına toplamaktayız. Şimdi ilk controller sınıfımızı oluşturalım.

  1. Solution Explorer’dan Controllers klasörüne sağ tuşla tıklayalım ve Add->Controller seçeneğini seçelim.
  2. Karşımıza gelen Add Controller penceresinden isim olarak HomeController ismini verelim. Zaten gelen pencerede sadece “Default1″ kısımını seçerek burayı değiştirmenizi isteyecek.
  3. Template olarak Empty girelim ve tamam tuşu ile onaylayıp sınıfımızı oluşturalım.

VWD IletisimController.cs dosyasını hazırlayarak önümüze sunacaktır. Hemen bir deneme yapmak için controller sınıfımızı aşağıdaki gibi düzenleyelim:

namespace Iletisim.Controllers
{
    public class HomeController : Controller
    {
        public string Index()
        {
            return "Merhaba dünya!";
        }
    }
}

Kaydedip ctrl+shift+b ile ya da projeye sağ tuşla tıklayıp build edelim. Eğer browser penceresini kapatmadı isek, sayfayı yenileyelim. Kapatmış isek saat’in yanındaki ASP.NET Developer Server ikonuna sağ tuşla tıklayıp Open in Web Browser seçeneğini seçelim.

Gördüğünüz gibi Home controller çalıştırıldı ve Index action metodu çağrıldı. Sonuçta ekrana istediğimiz bir text çıktı. Sayfanın kaynak koduna bakarsanız, sadece bizim belirlediğimiz string’den başka bir şey olmadığını göreceksiniz.

VWD yeni proje oluşturduğunda varsayılan olarak birincil controller ismini Home ve birincil action metodu da Index olarak atar. Yani ana sayfa ya da kök url (“/”) çağrıldığında Home controller sınıfına ait Index action metodu çağrılacaktır. İleride bunu nasıl değiştirileceğini öğreneceksiniz. Ama illaki kontrol etmek isterseniz Global.asax dosyasında ki RegisterRoutes metoduna göz atabilirsiniz.

Eğer Index metodunu View sayfasını gösterecek şekilde ayarlarsak ne olacağını görelim bunun için Index metodunu şu şekilde değiştirin ve derleyip sayfayı yenileyin:

        public ViewResult Index()
        {
            return View();
        }

Derleyip sayfayı yenilediğinizde hata mesajları ile karşılaşacaksınız. Bu hata mesajlarından da göreceğiniz gibi bu Index metoduna ait varsayılan View sayfalarının nerelerde arandığını liste halinde gösterilmektedir.

Şimdi bu controller’ı düzgün bir şekilde gösterecek bir view hazırlayalım. Bunun için ilk başta sayfada hangi verilerin olacağını düşünmeliyiz. Bu bir iletişim sayfası olduğundan basit bir kaç textbox olması bizim için kafi gelecektir. Controller ve View’lerde kullanılacak olan verilerin Model sınıfları ile ifade edildiğinden daha önce bahsetmiştik. Bu yüzden ilk başta veri modelimizi oluşturalım:

  1. Models klasörüne sağ tuş ile tıklayıp Add->Class seçeneğini seçelim.
  2. İsim olarak IletisimModel yazıp entere basalım.
  3. Oluşturulan yeni dosyayı aşağıdaki gibi düzenleyelim:
namespace Iletisim.Models
{
    public class IletisimModel
    {
        public string AdSoyad { get; set; }
        public string EPosta { get; set; }
        public string Telefon { get; set; }
        public string WebSitesi { get; set; }
        public string Mesaj { get; set; }
    }
}

Küçük bir ipucu: Özellikleri kolay bir şekilde oluşturmak için prop yazıp iki defa tab tuşuna basın.

Şu anda Controller ve View’lerde kullanılacak olan veri modelimizi oluşturmuş bulunmaktayız. Şimdi bu veri modeli kullanan bir View oluşturalım. Tabi ilk başta daha önce oluşturmuş olduğumuz controller sınıfını da bu modeli kullanacak şekilde değiştirelim:

  1. HomeController.cs dosyasını açın.
  2. Henüz değiştirmedi iseniz Index action metodunu aşağıdaki gibi değiştirin:
        public ViewResult Index()
        {
            return View();
        }
  1. Ctrl+Shift+B ile projeyi derleyin.
  2. Index metodunun üzerinde herhangi bir yerinde sağ tuş ile tıklayın ve “Add View…” seçeneğini seçin.
  3. Eğer Index metodunun üzerinde tıkladı iseniz VWD, View adı olarak bu action metodunun ismini verecektir. Eğer View name alanında Index yazmıyorsa Index yazacak şekilde değiştirin.
  4. View engine olarak yine Razor seçiyoruz.
  5. “Create a strongly typed view” seçeneğini işaretleyip altındaki kutucuktan IletisimModel isimli modeli seçelim. Eğer 3. adımdaki derleme işlemini yapmadı iseniz yeni oluşturduğunuz modeli burada göremezsiniz. Bu durumda buraya el ile Iletisim.Models.IletisimModel şeklinde model sınıfının ismini girmelisiniz.
  6. Template kısmını empty yani boş bırakın.
  7. “Use a layout or master page” seçeneğini kaldırın. Böylelikle herhangi bir layout veya master page kullanmamış olacağız.
  8. Diğer seçenekleri olduğu gibi bırakın ve Add tuşuna basın.

VWD bu işlemin ardından Views klasörüne controller sınıfımız ile aynı isimde yani Home isminde bir klasör oluşturacak ve bu klasörün içine Index.cshtml isimli bir view dosyası oluşturacak.Ve bu dosyanın içeriği şöyle bir şey olacak:

@model Iletisim.Models.IletisimModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
</head>
<body>
    <div>

    </div>
</body>
</html>

Üst kısımdaki kodlar hariç geri kalan kısım tamamen bildiğimiz saf html kodları. Yukarıdaki @model ile başlayan ilk satır, “Create a strongly typed view” seçeneği ile belirttiğimiz modeli kullanacağımızı ifade ediyor. Sonrasında gelen kod bloğu ise herhangi bir layout ya da master page kullanmayacağımızı ifade ediyor.

Şimdi projeyi derleyip browser sayfasını yenileyelim. Kaynak koda baktığımızda View dosyasındaki html kodlarının olduğunu göreceksiniz.

Şu anda çok basit bir Model-View-Controller mimarisini oluşturmuş bulunmaktayız. Her ne kadar şimdilik herhangi bir işlem yapmasa da MVC mantığını daha iyi kavramamızı sağlayacaktır. Kısaca işleyişi özetlersek; Browser’dan kullanıcı url’yi istekte bulunur, server bu url’ye atanmış olan controller’ın yani örneğimize göre Home controller’ın içindeki Index action metodunu çağırır. Ardından bu action metod, kendisine ait olan View sayfasını belirlenen veri modelini kullanarak çağırır ve kullanıcıya çıktı olarak gönderir.

Şimdi bu sayfamızı işler hale getirelim.

  1.  Index.cshtml view dosyasını açalım ve içeriğini aşağıdaki gibi değiştirelim(Kendi elinizle düzenlemenizi şiddetle tavsiye ediyorum.):
@model Iletisim.Models.IletisimModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>İletişim Sayfası</title>
</head>
<body>
    @using (Html.BeginForm())
    {
        <table border="0">
        <tr><th>Ad, Soyad: </th><td>@Html.TextBoxFor(m => m.AdSoyad)</td></tr>
        <tr><th>E-Posta: </th><td>@Html.TextBoxFor(m => m.EPosta)</td></tr>
        <tr><th>Telefon: </th><td>@Html.TextBoxFor(m => m.Telefon)</td></tr>
        <tr><th>Websitesi: </th><td>@Html.TextBoxFor(m => m.WebSitesi)</td></tr>
        <tr><th>Mesaj: </th><td>@Html.TextAreaFor(m => m.Mesaj)</td></tr>
        </table>
        <input type="submit" value="Gönder" />
    }
</body>
</html>

Küçük bir ipucu: View dosyalarında yaptığınız değişiklikleri görmek için projeyi tekrar derlemenize gerek yok. Browser’dan direk olarak sayfayı tazelemeniz yeterli olacaktır.

  1. Home controller sınıfımıza geçelim ve aşağıdaki değişiklikleri yapalım:
namespace Iletisim.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public ViewResult Index()
        {
            return View();
        }

        [HttpPost]
        public ViewResult Index(IletisimModel iletisimModel)
        {
            return View("Tesekkur", iletisimModel);
        }
    }
}

Küçük bir ipucu: Eğer IletisimModel sınıfını bulamadığından dolayı altı kırmızı ile çizilirse, klavye imlecini buraya getirin ve ctrl+nokta tuşlarına basın. Intellisense sizin için bu sınıfı arayacak ve using ile referansı ekleminizi sağlayacaktır.

Buraya kadar ne yaptığımıza bir göz atalım.

İlk adımımızda view sayfamızda bir form oluşturduk. Bunun için Html yardımcı metodlarından yararlandık. Bunları kullanmak zorunda değildik fakat ileride kullandıkça göreceğiniz gibi bu yardımcı metodlar model sınıfı ile birlikte çalışarak işlemlerimizi daha da kolaylaştırıyor.

Bu yardımcı metodlardan ilki, bir html formu oluşturmamıza yarayan Html.BeginForm() metodudur. Bu metod diğerlerinden farklı olarak using kelimesi ile beraber kullanılıyor. Böylece using kod bloğu içindeki tüm kodlar, form elementinin içine yerleştiriliyorlar. Sayfayı browser’dan yenileyip kodlarına baktığınızda, göreceğiniz gibi using kod bloğunun başlangıcında form elementinin başlangıç tag’ı(<form>) ve kod bloğunun bitişinde de form elementinin bitiş tag’ı(</form>) yer almaktadır. Bu metodun diğer paremetre ve ayarlarına burada deyinmeyeceğim. Ama tek söyleyeceğim bu metod varsayılan olarak form elementinin POST veri gönderecek şekilde ayarladığıdır. Zaten kaynak kodlara baktığınızda siz de bunu farkedeceksiniz.

Html.TextBoxFor() ve Html.TextAreaFor() metodları ise paremetre olarak delegate tipinde veri alıyor. Bu metodlara paremetre olarak lambda kullanılarak model yapımıza ait özellikler ile ilişkilendirme yapıyoruz. Burada delegate kullanmamak için TextBox() ve TextArea() metodları da kullanılabilir fakat bu şekilde model yapımıza bu form elementlerini bağlamamız biraz daha uzun olacaktır. Üstelik delegate ve lambda kullanarak yazım yanlışlarının da önüne geçmiş oluyoruz. Özellikle ilk maddede bu kodları kendi elinizle yazmanızı istememin esas sebebi bu idi. “(m => m.” yazdıktan sonra intellisense’in çıkardığı listenin, daha önce tanımlamış olduğumuz Model sınıfına ait olduğuna dikkat edin.

İkinci adımda ise controller sınıfımıza başka bir Index metodu daha ekledik. Ve bu metodlardan ilkini HttpGet ve diğerini HttpPost öznitelikleri(attribute) ile ilşikilendirdik. Böylelikle GET ile gelen bir istek ilk Index metodunu, POST ile gelen bir istek ise ikinci Index metodunu çalıştıracaktır. Bildiğiniz gibi her hangibir url’yi browser’dan talep ettiğimizde browser server’dan GET ile istekte bulunur. Yani bu örneğimize göre, kullanıcı sitenin url’sini browser’a yazıp entere bastığında ilk Index metodu çalışacaktır. Velevki herhangi bir form verisi sayfaya POST edilirse, bu durumda HttpPost ile ilişkilendirilmiş olan ikinci Index metodu çalıştırılacaktır. View sayfamızda oluşturmuş olduğumuz form elementi POST veri yolladığında, ikinci Index metodu faaliyete geçecektir.

Burada ikinci Index metodundaki View sayfasını çağıran View() metoduna dikkat edin. Bu View() metodu, bu action metoda ait view sayfasını değil başka bir view sayfasını çağırmanızı sağlar.  Bunun gibi View metodunun bir çok overload versiyonları vardır. Tüm bu overload edilmiş metod çeşitleri için yardım dosyasına ya da Intellisense yardımına bakabilirsiniz. Biz bu örneğimizde view sayfasına belirlediğimiz modeli parametre olarak yollayan metodu kullanmayı seçtik.

Projeyi derleyip browser’da sayfayı yenileyin ve form’daki Gönder düğmesine basın. Karşılık olarak “Tesekkur” view dosyasının bulunamadığna dair bir hata mesajı alacaksınız. Buradan varsayılan olarak nerelerde bu dosya arandığını liste halinde görebilirsiniz. Bu view sayfasını da oluşturup ekrana teşekkür mesajı yazdıralım:

  1. Home controller dosyasında herhangi bir yerde sağ tuş ile yıklayın ve “Add View..” seçeneğini seçin.
  2. View name olarak Tesekkur girelim.
  3. “Create a strongly typed view” seçili olacak şekilde Model class olarak yine IletisimModel modelini seçelim.
  4. Template’i empty girelim ve yine “use a layout or master page” seçeneğini kaldırıp Add tuşuna basalım.
  5. Tesekkur view dosyasını aşağıdaki gibi değiştirelim:
@model Iletisim.Models.IletisimModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Teşekkür ederiz!</title>
</head>
<body>
    <div>
        <p>Sayın @Model.AdSoyad,</p>
        <p>Bizimle irtibata geçtiğiniz için teşekkür ederiz.
        Size en kısa zamanda @Model.EPosta e-posta adresinizden
        ya da @Model.Telefon nolu telefonunuzdan ulaşacağız.</p>
        <p>İyi günler.</p>
    </div>
</body>
</html>

Şimdi bu şekilde projemizi derleyip sonucu browser’da gözlemleyelim. Formda ki textboxlara bir şeyler yazalım ve Gönder tuşuna basalım.

Gördüğünüz gibi “Tessekkur” view dosyamız hazırladığımız gibi ekrana basıldı. Fakat henüz controller sınıfımız, formdan gelen bu verileri işleyecek durumda değil. İlk başta form verilerinin uygunluğu kontrol edilmeli. Bunun için validation yani doğrulama kontrolü yapmamız gerek.

  1. IletisimModel isimli model sınıfımıza aşağıdaki gibi eklemeler yapalım:
    public class IletisimModel
    {
        [Required(ErrorMessage="Adınız ve soyadınız gerekli.")]
        public string AdSoyad { get; set; }

        [Required(ErrorMessage="Bir e-posta adresi girmelisiniz.")]
        [RegularExpression(".+\\@.+\\..+",
            ErrorMessage="Girdiğiniz e-posta geçerli değil.")]
        public string EPosta { get; set; }

        [Required(ErrorMessage="Bir telefon girmelisiniz.")]
        public string Telefon { get; set; }

        public string WebSitesi { get; set; }

        [Required(ErrorMessage="Bir mesaj girmelisiniz.")]
        [StringLength(500, MinimumLength=10,
            ErrorMessage="Girdiğiniz mesaj 10 ila 500 karakter arasında olabilir.")]
        public string Mesaj { get; set; }
    }
  1. Home controller dosyasını açalım ve HttpPost öznitelikli Index metodumuzu şu şekilde değiştirelim:
        [HttpPost]
        public ViewResult Index(IletisimModel iletisimModel)
        {
            if (ModelState.IsValid)
            {
                return View("Tesekkur", iletisimModel);
            }
            else
            {
                return View();
            }
        }
  1.  Son olarak Index view dosyamızı açıp şu değişikliği yapalım:
<body>
    @Html.ValidationSummary()<br />
    @using (Html.BeginForm())
    {
        <table border="0">

Projemizi derleyelim ve browser ile sayfamızı tazeleyelim. Sonucu gözlemlemek için textboxları boş bırakalım ve formu gönderelim.

Gördüğünüz gibi Tesekkur view sayfası yerine tekrar Index’e döndük. E-posta ve mesaj alanları haricindekileri düzgün bir şekilde dolduralım ve e-posta alanına e-posta adresi olmayan bir şey girelim ve mesaj alanına da 10 karakterden az bir şeyler yazalım ve formu gönderelim. Bu sefer de belirlediğimiz diğer doğrulama mesajlarını göreceksiniz.

İlk maddeden başlayarak kodlarımızı açıklayalım. İlk maddede model sınıfımıza bazı öznitelikler(attribute) ekledik. Bunlar System.ComponentModel.DataAnnotations alanında tanımlıdırlar. Bu yüzden eğer bu öznitelikleri yazdığınızda altları kırmızı ile çizilirse using ile bu alanı tanıtmalısınız (ya da ctrl+nokta ile otomatik eklettirebilirsiniz). Bu alan altında doğrulama yapabileceğiniz bir çok öznitelik mevcutur. Biz burada bir kaçını gösterdik. En basit doğrulama özniteliği Required özniteliğidir ve gerekli manasında olup alanın boş olup olmadığını kontrol eder. Yine ReqularExpression ile e-posta’nın uygun olup olmadığını kontrol için bir regexp tanımladık. Buraya yazdığımız regular expression bizim makalemizin konusu değil. Aynı şekilde StringLength ile alanın karakter boyutunu sınırlandırmış olduk.

İkinci maddede ise controller sınıfımızdaki HttpPost ile ilişkilendirilmiş olan Index metodumuz model verilerinin doğru olup olmadığını öğreniyor. Sonucunda doğru değilse form yani Index view dosyası tekrar gösteriliyor. Bunun için kullanılan özellik ModelState.IsValid özelliğidir.

En son olarak hata mesajlarını formumuz üzerinde göstrermek için @Html.ValidationSummary() metodundan faydalandık. Eğer sayfanın kaynak koduna bakarsanız textbox’lara da bazı class değerleri eklendiğini görebilirsiniz. Bu sayede, biz burada yapmadık ama, hatalı giriş yapılmış textboxları css ile belirtebilirsiniz.

Tabi ki bu doğrulama en basit ve varsayılan şekliyle karşımızda. Fakat daha karmaşık doğrulamaları da MVC ile çok rahat bir şekilde yapabiliyorsunuz. Hatta view sayfasına eklediğimiz hata mesajlarının yapısını bile çok rahat bir şekilde değiştirebilirsiniz.

Aslında örneğimizin MVC ile ilgili kısmı bitmiş durumda. Fakat en son olarak mail gönderme işlemini de kodlarımıza ekleyelim ve projemizi tamamlamış olalım. Tesekkur view dosyasını açalım ve aşağıdaki eklemeleri yapalım:

</head>
<body>
    @{
        try
        {
            WebMail.SmtpServer = "smtp.birsunucu.com";
            WebMail.UserName = "kullanıcı adı";
            WebMail.Password = "şifre";
            WebMail.From = "iletisimformu@deneme.com";
            WebMail.Send("info@deneme.com", "İletişim Formu Mesajı", @<text>
                <p>Aşağıda bilgileri bulunan şahıs iletişim formunu doldurmuştur</p>
                <p>Adı Soyadı: @Model.AdSoyad</p>
                <p>E-Posta: @Model.EPosta</p>
                <p>Telefon: @Model.Telefon</p>
                <p>Web Sitesi: @Model.WebSitesi</p>
                <p>Mesaj: @Model.Mesaj</p>
                </text>);
            }
        catch (Exception)
        {
            @:<strong>E-posta gönderirken bir hata ile karşılaştık. Lütfen daha sonra tekrar deneyiniz.</strong>
        }
    }
    <div>
        <p>Sayın @Model.AdSoyad,</p>

Başka şekillerde de e-posta gönderimi yapılabilir. Biz burada view içinde mail göndermeye çalıştık fakat controller içinde de bu gönderim yapılabilir. Buradaki amacım daha çok Razor gramerine aşinalığınızı artırmaktır. Özellikle WebMail.Send metoduna girdiğimiz üçüncü parametreye dikkat ediniz.

İnanıyorum MVC ve Razor’u benim kadar sevdiniz. Benden şimdilik bu kadar, yorumlarınızı bekliyorum.

İlerleyen zamanlarda başka MVC makaleleri ile karşınızda olabilirim. Klavyenize zeval gelmesin !

Fatih Tolga Ata © 2011

» Tags: , ,

12 Yorum

  • At 2011.08.07 16:22, Fatih Tolga Ata said:

    Wauw.. iki buçuk sene geçmiş son makalemden bu yana. Baya boşlamışız siteyi. Biraz canlılık gelsin artık :)

    • At 2011.08.07 17:09, arif emre said:

      maşallah çok güzel olmuş fatih… eline sağlık…

      • [...] > ASP.NET | MVC > ASP.NET MVC – Proje, Yönlendirme« Previous|ASP.NET MVC – Proje, Yönlendirme Posted on 14 Ağustos 2011 | Yorum YapılmamışGeçen [...]

        • At 2011.08.22 01:38, selim er said:

          Oldukça detaylı, anlaşılır, akıcı bir makale olmuş. Bir kerede okudum ve aklımdaki bir çok kör nokta aydınlandı. Çok çok teşekkür ediyorum.
          iyi çalışmalar..

          • At 2011.09.09 21:26, Hersoy said:

            Tebrik ederim okuduğum en akıcı ve anlaşılır bir makale idi.çok teşekkürler

            • At 2011.09.09 21:27, Hersoy said:

              Çok teşekkür ederim

              • At 2011.09.21 21:51, Kudret Efil said:

                Çok güzel bir makale çok teşekkürler, mvc nedir birader soruma süper cevap aldım.

                • At 2011.11.06 01:14, Can Aktepe said:

                  Merhaba öncelikle belirtmek isterimki 1 saat önce mvc ye göz atma ve yavaş yavaş başlama kararı aldım.. Mükemmel bir makale olmuş ancak kodları tek tek denedim son aşamada bir problem oluştu mail gönderme bölümünde

                  Compilation Error
                  Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.

                  Compiler Error Message: CS1660: Cannot convert lambda expression to type ‘string’ because it is not a delegate type

                  hatası alıyorum…

                  • At 2011.11.06 05:53, Fatih Tolga Ata said:

                    Şu anda derleyip bakma imkanım yok. Tahminime göre “@” işaretinin kullanımında sıkıntı var. text etiketinden önceki @ işaretini kaldırmayı deneyebilirsiniz.

                    • At 2011.12.12 18:28, selim er said:

                      Fatih bey çok teşekkür ediyorum. Benim için fazlasıyla faydalı oldu.
                      Çok sağolun

                      • At 2011.12.28 19:42, Yasin Özel said:

                        Hocam vidolu anlatımlar boş yere uzun zaman harcadığı için pek hoşuma gitmiyordu. Bu nedenle makalenizi okudum. Bana ne kadar çok şey kattı tahmin bile edemezsiniz. Çok çok teşekkür ediyorum.

                        • At 2012.01.24 22:56, cengiz said:

                          Bende MVC ye yeni göz atmaya başladım ve makale çok faydalı oldu. Gerçekten güzel ve detaylı anlatım. Emeğinize sağlık cok teşekkür ediyorum

                          (Required)
                          (Required, will not be published)

                          Switch to our mobile site