Asp.Net Mvc – Yeni Üye Kaydı ve Dosya Yükleme – Üyelik Sistemi 1 (Asp.Net Mvc Yazı Dizisi – 20)

Merhaba Arkadaşlar,

Geliştirmeyi sürdürdüğümüz blog projemizde, makalelerin, etiketlerin ve yorumların görüntüleneceği kısımları oluşturmuştuk. Bundan sonraki süreçte ise, sistemimizde üyelik sistemini aktif edeceğiz. Üyelik sistemimizin içeriğinde ise aşağıdaki özellikler olacak.

  • Üye girişi
  • Üye olma
  • Yetkilendirme

Yukarıdaki saydığımız şeyleri sisteme entegre etmeden önce, belirtmekte fayda gördüğüm bazı hususlar var;

Öncelikle web mimarisinde, sayfa sunucudan herhangi bir engelleme olmadan çıktığında, tarayıcıda görüntülenir. Bu yüzden biz yetkilendirme ya da filtreleme işlemlerini sunucuda yapıyor olacağız. Böylelikle sayfa daha hazırlanırken, kullanıcıdan aldığımız bilgilerle (kullanıcı adı, üyelik hakları vs.), sayfanın erişimini istediğimiz gibi ayarlama şansına sahip olacağız.

Kabaca sistem hakkında, ön bilgiler verdikten sonra, işlemlerimizi yapmaya başlayalım.

Yeni Üyelik Sayfası

  • Öncelikle, önceki derslerde kullandığımız projemizin son halini açalım. (İndirmek için lütfen tıklayınız.)
  • Veritabanımızı tasarlarken eklemeyi unuttuğumuz, Uye tablosuna Sifre kısmını ekleyelim. Eklememizi yaptıktan sonra, Data>Uye.cs dosyamızın içeriği aşağıdaki gibi görünecektir.
using System;
using System.Collections.Generic;

//Bu isim uzayını eklememizin sebebi, [DataType],[StringLength] gibi Attribute'leri tanımlıyor olmamız.
using System.ComponentModel.DataAnnotations;

using System.Linq;
using System.Web;

namespace MvcProjesi.Data
{
    public class Uye
    {
        //Bu alan tablonun id'si olacak. Tablo adının sonuna Id takısı eklendiğinde, framework bu alanı otomatik olarak, 
        //tablonun anahtar sütunu yani primary key'si yapacaktır. Bu varsayılanı değiştirmek mümkündür, ancak bu konuya 
        //girmeyeceğiz. Detaylı bilgi için, Code First Fluent olarak araştırma yapabilirsiniz.
        public int UyeId { get; set; }

        //Bu alanı zorunlu hale getiriyoruz. Böylelikle boş geçilemeyecek.
        [Required(ErrorMessage = "Lütfen adınızı giriniz.")]
        //Girilen metnin uzunluğunu belirtiyoruz. İlk değişken minimum uzunluk olurken, sonrakiler ise, opsiyonel 
        //girdilerdir.
        [StringLength(50, MinimumLength = 3, ErrorMessage = "Adınızı 3-50 karakter arasında girebilirsiniz.")]
        public string Ad { get; set; }

        [Required(ErrorMessage = "Lütfen soyadınızı giriniz.")]
        [StringLength(50, MinimumLength = 3, ErrorMessage = "Soyadınızı 3-50 karakter arasında girebilirsiniz.")]
        public string Soyad { get; set; }

        [Required(ErrorMessage = "Lütfen e-posta adresinizi giriniz.")]
        //Girilen metnin, geçerli bir e-posta adresi formatında girilmesini sağlıyoruz. 
        //DataType tipleri, Microsoft tarafından Framework'e eklenen hazır tiplerdir.
        [DataType(DataType.EmailAddress, ErrorMessage = "Lütfen e-posta adresinizi geçerli bir formatta giriniz.")]
        public string EPosta { get; set; }

        //Required Attribute'si eklemediğimiz için, bu alan zorunlu olmayacak ve boş geçilebiliyor olacak.
        //Girilen metnin, geçerli bir web sitesi adresi formatında girilmesini sağlıyoruz. 
        [DataType(DataType.Url, ErrorMessage = "Lütfen web site adresinizi, geçerli bir formatta giriniz.")]
        public string WebSite { get; set; }

        //Girilen metnin, geçerli bir resim yolu formatında girilmesini sağlıyoruz. 
        [DataType(DataType.ImageUrl, ErrorMessage = "Lütfen resim yolunuzu doğru şekilde giriniz.")]
        public string ResimYol { get; set; }


        [Required(ErrorMessage = "Lütfen üye olma tarihini giriniz.")]
        //Girilen tarihin, geçerli bir tarih ve saat formatında girilmesini sağlıyoruz.
        [DataType(DataType.DateTime, ErrorMessage = "Lütfen üye olma tarihini, doğru bir şekilde giriniz.")]
        public DateTime UyeOlmaTarih { get; set; }

        //Bir üyenin, birden çok yorumu olabileceği için Yorumları bir liste içerisine alıyoruz. 
        //Property adının sonuna s takısı koymamızın sebebi, veri tipinin çoğul olduğunun daha kolay anlaşılabilmesi 
        //içindir. Entity varsayılan olarak, liste verilerin sonuna s takısı koymaktadır.
        //Biz de bu standarda uyum gösterdik. Eğer veri tipinin adı zaten s ile bitiyorsa o zaman da s yi siliyoruz.
        //Örneğin hayvanlarla ilgili bir tabloda, Kus adlı bir sınıfımız çoğul olarak temsil edilecekse Ku olarak 
        //kullanabiliriz.
        public virtual List<Yorum> Yorums { get; set; }

        //Bir üyenin eklediği, birden çok makale olabilir.
        public virtual List<Makale> Makales { get; set; }

        //Baştan eklemeyi unuttuğumuz şifre kısmını ekledik.
        [DataType(DataType.Password)]
        [Required(ErrorMessage = "Lütfen şifrenizi giriniz.")]
        public string Sifre { get; set; }
    }
}
  • Şifre güncellemesinin, veritabanına yansıtılması için, veritabanı adımızı değiştirelim. (Normalde tablo yapısında değişiklik olduğunda, Code First Migrations yöntemi ile değişiklerin uygulanması sağlanır, tablo isimleri değiştirilmez. Bu konuya ileri seviye derslerde değinilecektir. İlgilenen arkadaşlar, detaylı bilgiye şuradan bakabilirler.) Tablo ismimizi değiştirmek için, ana dizinde bulunan web.config dosyasındaki, 
 <add name="MvcProjesiContext" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=MvcProjesiYeni;Integrated Security=True" providerName="System.Data.SqlClient" />

satırını,

 <add name="MvcProjesiContext" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=MvcProjesiSon;Integrated Security=True" providerName="System.Data.SqlClient" />

olarak güncelleyelim.

  • Son olarak da, Global.asax dosyamızda, veritabanı ilk oluşturulduğunda, yeni üye kaydı yapılırken hata almamamız için, 
 Uye uye = new Uye() { Ad = "Abdurrahman", Soyad = "Güngör", EPosta = "abdurrahmangungor@deneme.com", ResimYol = "", UyeOlmaTarih = DateTime.Now, WebSite = "http://www.abdurrahmangungor.com" };

kısmını,

 Uye uye = new Uye() { Ad = "Abdurrahman", Soyad = "Güngör", EPosta = "abdurrahmangungor@deneme.com", ResimYol = "", UyeOlmaTarih = DateTime.Now, WebSite = "http://www.abdurrahmangungor.com",Sifre="deneme" };

olarak değiştirelim.

  • İşlemlerimizde varsayılan olarak kullandığımız, HomeController'in yerine üyelik vb. işlemlerimiz için, UyelikController adında yeni bir Controller kullanalım.
  • Controllers klasörüne sağ tıklayıp, Add>Controller diyelim. Çıkan ekrandaki seçimi aşağıdaki gibi yapıp, Add tuşuna tıklayalım.

Controller ekleme ekranı

Controller isim verme

  • Yeni Controller'imizi eklediğimizde, Index Action'u varsayılan olarak gelmiş bulunmaktadır. Biz bu Action'umuzu kaldıralım.
  • Şimdi, yeni üyelik ekranını hazırlayalım. Bunun için öncelikle, Controller'imize aşağıdaki Action'u ekleyelim.
 public ActionResult YeniUyelik()
        {
            return View();
        }

Görüldüğü üzere, tek yaptığımız şey, geriye bir View sayfası döndürmek.

  • Şimdi ise, View sayfamızı oluşturup içeriğini dizayn edelim. Bunun için yapmamız gereken şey ise, YeniUyelik() kısmına sağ tıklayarak, Add View' a tıklamak ve içeriğini aşağıdaki gibi düzenlemek;

Yeni üyelik View eklenmesi

Dikkat edeceğiniz üzere, Views'in altına Uyelik klasörü ve YeniUyelik.cshtml dosyası otomatik olarak oluşturuldu.

  • View sayfamızın içerisine girelim ve içeriğini aşağıdaki gibi hazırlayalım.
@model MvcProjesi.Data.Uye

@{
    ViewBag.Title = "Yeni Üyelik";
}
<!--Layout sayfamızda sayfanın en alt kısmında scripts adlı bir sectionumuz tanımlanmıştı.
    Script ve css kodlarımızı scripts sectionuna koyacağız.
    Detaylı bilgi önceki yazılarımızda vardır.-->
@section scripts{
    <style type="text/css">
        #formKapsayici {
            box-shadow: 0 0 5px gray;
            padding: 25px;
            height: 500px;
        }

        #divSol, #divSag {
            float: left;
            margin-left: 25px;
        }

            #divSol *, #divSag * {
                margin-top: 15px;
            }

        input[type="text"] {
            width: 250px;
        }

        #btnUyeOl {
            /*clear komutu ile önceki divlerin sola yaslanarak sıralanmasında, butonun bu yaslanmaya
            uymayıp alt satıra inmesini sağlıyoruz*/
            clear: both;
            display: block;
            margin-left: 132px;
        }
    </style>

    <!--Projemizde tarih seçici kullanacağız. Bunun için Jquery ve Jqueryui den faydalanacağız.-->

    <!--Öncelikle gerekli Jquery ui kütüphanemizi ekliyoruz. Jquery kütüphanemiz Layout sayfamızda
        zaten tanımlanmış durumdadır.-->
    <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css" />
    <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
    <!--Kütüphanelerimizin online olduğunu bu yüzden sayfa çalışırken, internet bağlantımızın aktif olması
        gerektiğini lütfen göz önünde bulundurun.-->

    <!--Tarih seçicimizi burada hazırlayacağız-->
    <script type="text/javascript">
        $(document).ready(function () {
            $("#textBoxDogum").datepicker();
        });
    </script>
}
<h2>Yeni Üyelik</h2>

<!--Html.BeginForm ile yeni bir form oluşturuyoruz ve içeriğine elemanlarımızı ekliyoruz.-->
<!--Formumuzun içinde resim yüklemesi de yapacağımız için, forma enctype = "multipart/form-data" özelliği veriyoruz-->
<!--Ayrıca normalde sistemimize doğum gününü kaydetmeyecektik, bu yüzden bir örnek olması adına Jquery ile 
    doğum tarihini alarak, yaş kontrolü yapacağız.-->
<!--Formun sunucuya gönderim yöntemini, FormMethod.Post yaptığımıza dikkat edin.
Get ve Post metodları hakkında internette araştırma yapmanızda fayda var.-->

@using (Html.BeginForm("YeniUyelik", "Uyelik", FormMethod.Post, new { enctype = "multipart/form-data", id = "formKapsayici" }))
{
    <div id="divSol">
        @Html.LabelFor(i => Model.Ad)<br /><br />
        @Html.LabelFor(i => Model.Soyad)<br /><br />
        @Html.LabelFor(i => Model.EPosta)<br /><br />
        @Html.LabelFor(i => Model.Sifre)<br /><br />
        @Html.LabelFor(i => Model.WebSite)<br /><br />

        <!--Tüm elemanlarda for takısını kullanırken doğum tarihi ve resim yüklemede kullanmadık.
            Çünkü bu iki elaman daha önce hazırladığımız Uye modeline ait değiller.
            Bu yüzden elle ekledik.-->
        @Html.Label("Doğum Tarihiniz")<br /><br />
        @Html.Label("Profil Resminiz")<br /><br />
    </div>
    <div id="divSag">
        : @Html.TextBoxFor(i => Model.Ad)<br /><br />
        : @Html.TextBoxFor(i => Model.Soyad)<br /><br />
        : @Html.TextBoxFor(i => Model.EPosta)<br /><br />
        : @Html.TextBoxFor(i => Model.Sifre)<br /><br />
        : @Html.TextBoxFor(i => Model.WebSite)<br /><br />
        : @Html.TextBox("textBoxDogum")<br /><br />

        <!--Aşağıdaki input type="file" dosya yüklemeye yarayan, html elementidir.-->
        <input type="file" id="inputFile" name="file" /> <br /><br />

    </div>
    <input type="submit" value="Üye Ol" id="btnUyeOl" />

    <!--Html.ValidationSummary ile formda oluşan geçerlilik hatalarını liste halinde gösterebiliyoruz.-->
    @Html.ValidationSummary()
}

Projemizde üye olma sayfasında, Jquery Ui tabanlı çalışan tarih seçiciyi kullandık. Jquery ve Jquery Ui ile alakalı ayrı bir dersde bilgilendirmelerde bulunacağız. Kısaca en popüler, Javascript kütüphanesi diyebiliriz. JavaScript ile ilgili işlerimizi oldukça kolaylaştıran şahane bir yapıdır.

Sayfamızı tamamladığımızda, sayfamız aşağıdaki gibi görünecektir.

Jquery ui Date Picker

  • Şimdi ise, View sayfamızdan gelen bilgilerle kayıt yapılacak, Action'a ihtiyacımız var.
  • Action'u eklemeden önce, projemizin ana dizinine Images klasörü ekleyelim. Kullanıcıların resimlerini, bu klasör içerisine ekleyeceğiz. 
  • Klasörümüzü de ekledikten sonra, kayıt için kullanacağımız Action'larımızı aşağıdaki gibi ekleyelim.
//Formumuzun geliş metodu Post
        //Dikkat ederseniz aynı isimli, iki adet Action var.
        //Üsttekinin metodu boş olduğu için Get oluyor.
        //Alttakinin üzerinde [HttpPost] olduğu için metodu Post oluyor.
        //Burada eğer sayfa içinden bir form gönderimi yapılmışsa, Post olan Action çağrılır.
        //Normal adres üzerinden sayfaya talepte bulunulursa, Get metodlu olan çağrılır.
        [HttpPost]
        public ActionResult YeniUyelik(Uye model, string textBoxDogum, HttpPostedFileBase file)
        {
            if (!ModelState.IsValid)
            {
                return View();
            }
            if (String.IsNullOrEmpty(textBoxDogum))
            {
                //Burada Uye modelimizde olmayan bir elemanla çalıştığımız için, kendimiz elle hata
                //mesajını, sayfadaki hata listesine (@Html.ValidationSummary()) ekliyoruz.
                ModelState.AddModelError("textBoxDogum", "Doğum tarihi boş geçilemez");

                //Hata oluşması halinde sayfayı tekrar yüklüyoruz.
                //Böylelikle otomatik olarak hatalar sayfada gösteriliyor.
                return View();
            }
            int yil = int.Parse(textBoxDogum.Substring(6));
            if (yil > 2002)
            {
                ModelState.AddModelError("textBoxDogum", "Yaşınız 12 den küçük olamaz");
                return View();
            }
            Uye uye = new Uye();
            if (file != null)
            {
                //Sunucuya dosya kaydedilirken, sunucunun dosya sistemini, yolunu bilemeyeceğimiz için
                //Server.MapPath() ile sitemizin ana dizinine gelmiş oluruz. Devamında da sitemizdeki
                //yolu tanımlarız.
                file.SaveAs(Server.MapPath("~/Images/") + file.FileName);
                uye.ResimYol = "/Images/" + file.FileName;
            }
            uye.Ad = model.Ad;
            uye.EPosta = model.EPosta;
            uye.Soyad = model.Soyad;
            uye.UyeOlmaTarih = DateTime.Now;
            uye.WebSite = model.WebSite;
            uye.Sifre = model.Sifre;
            using (MvcProjesiContext db = new MvcProjesiContext())
            {
                db.Uyes.Add(uye);
                db.SaveChanges();

                //İşlemimiz başarıyla biterse, başarılı olduğuna dair bir sayfaya yönlendiriyoruz.
                return RedirectToAction("UyelikBasarili");
            }
        }

        public ActionResult UyelikBasarili()
        {
            return View();
        }
  • İşlemlerimizi yapıp, projeyi çalıştırıp, ardından da Yeni Üyelik linkine tıklarsak hata sayfasıyla karşılaşacağız. Bunun sebebi ise, kullandığımız linkteki, Controller'in Home olması. Biz onu, Uyelik ile değiştireceğiz.
  • Bunun için, Views>Shared>_Layout.cshtml sayfamızı açalım.
  • Aşağıdaki iki satırı,
 <li>@Html.ActionLink("Üye Girişi", "UyeGiris", "Home")</li>
                    <li>@Html.ActionLink("Yeni Üyelik", "YeniUyelik", "Home")</li>

aşağıdaki iki satır ile değiştirelim.

 <li>@Html.ActionLink("Üye Girişi", "UyeGiris", "Uyelik")</li>
                    <li>@Html.ActionLink("Yeni Üyelik", "YeniUyelik", "Uyelik")</li>

27.04.2014 tarihli ekleme

UyelikBasarili.cshtml sayfasını makale içerisinde eklemediğimi bir arkadaşın uyarısıyla farkettim. Siz bu eklemeyi, kolaylıkla yapabilirsiniz. İçeriğini istediğiniz gibi doldurabilirsiniz. Ben içeriğe makale eklemiştim.

  • İşlemlerimizi yaptıktan sonra, projemizi çalıştıralım.
  • Yeni Üyelik sayfamıza girelim ve üye olalım.
  • Üyeliğimiz başarılı olduğunda, aşağıdaki ekranla karşılaşacağız.

Üyelik Başarılı ekranı

Burada dikkat edilmesi gereken nokta, kullanıcının şifresini direkt veritabanına kaydettik. Normal projelerde bu yöntem asla kullanılmaz. Şifre önce, SHA1 ya da MD5 gibi yöntemlerle hashlenir ve hash olarak kaydedilir. Ayrı bir konu olarak Microsoft'un sunduğu Authentication yapısını inceleyeceğiz. Bu yapı bu tarz işlemleri otomatik olarak halletmektedir.

Sonraki dersimizde, üyelik işlemlerine devam ediyor olacağız.

 

Projenin son halini buradan indirebilirsiniz.

Hepinize kolaylıklar diliyorum.