Profil sayfası kişiselleştirme ve ComplexType

Başlık biraz karışık oldu sanırım, biraz açayım. Profil sayfası kişiselleştirme dediğim; Twitter, FriendFeed gibi sayfalarda arkaplan resmini, konumunu ve renkleri isteğimize göre düzenleyebiliyoruz, yani profilimizi kişiselleştirebiliyoruz. ComplexType ise ilk konudan bir hayli alakasız aynı zamanda ComplexType olayını anlamak için çok alakalı. En kaba tabirle; modelimizde ki belirli özellekleri kümelediğimiz ve kod yazarken bize çok büyük kolaylık sağlayan bir yaklaşım.

Öncelikle modelimizi oluşturalım ve ComplexType nedir ona bir bakalım. Senaryo şu şekilde. Kullanıcılarımız sayfalarını istedikleri gibi kişiselleştirebiliyor. Bu sebepten dolayı ilgili bilgileri veritabanında tutmamız gerekiyor. Öte yandan kullanıcıya ait ana bilgileride veritabanında tuttuğumuzu düşünürsek karışıklık olmasın diye bu iki tabloyu birbirinden ayrı ve ilişkilendirilmiş bir şekilde tasarlamamız olası bir durum. ComplexType ile birlikte bu karmaşayı ortadan kaldırabiliyoruz. Tablonun içinde tüm alanlar bulunuyor fakat kod yazarken kümelediğimiz isim üzerinden ilgili alanlara ulaşabiliyoruz. Örneğin bu kullanıcının adres bilgileri de aynı tabloda olsaydı, oldukça karmaşık bir durum söz konusu olacaktı. Aşağıda ki modelde kullanici isimli sınıfın içine kisisel adında bir ComplexType tanımlıyoruz ve kod yazarken kullanici yazıp noktaya bastığımızda, kisisel adında bir özellik görüyoruz, bu özelliğin içinde ise kisisel sınıfı içindeki alanlara erişebiliyoruz. Bu durumda veritabanımız şu şekilde oluşuyor;

Gördüğünüz gibi kisisel_ ön ekiyle birlikte alanlarımız oluşmuş oldu. Buradaki isimlendirmeyi Fluent Api ile birlikte düzenlememiz de mümkün. Eğer adres bilgilerinide kümelediğimiz bir ComplexType ımız olsaydı aynı tablo içinde adres_ ön ekiyle ve kullanıcı modelini kullanırken kullanici.adres.* şeklinde ilgili alanlara erişebilecektik, bu sayede kod yazarken adresle ilgili bilgilerin adresin altında, kişiselleştirme ile ilgili bilgilerin kisiselin altında olduğunu anlayacaktık ;) Konuyla ilgili uygulama yaparsanız çok daha iyi anlayacaksınız.

Projemizde kullanacağımız modelimiz aşağıdaki gibi olacak..

    public class kullanici
    {
        public kullanici() {
            kisisel = new kisisel();
        }

        public int id { get; set; }
        public string kullaniciAdi { get; set; }
        public string eposta { get; set; }
        public string sifre { get; set; }
        public kisisel kisisel { get; set; }
    }

    public class kisisel
    {
        public string bgColor { get; set; }
        public string bgImage { get; set; }
        public string bgPosition { get; set; }
        public string bgStyle { get; set; }
    }

Modelimizi oluşturduktan sonra işin zevkli kısmına geçebiliriz. Modelimize ait kontrollerimizide oluşturduktan sorna, Edit.cshtml sayfasına girip ilgili düzenlemeleri yapıyoruz. Kişiselleştirme için arkaplan rengini düzenleyeceğimizden bir renk seçme paletine ihtiyacımız var, ben farbtastic i kullandım. Mevcut Edit.cshtml sayfasına farbtastic in dosyalarını ekliyoruz ve şu şekilde değiştiriyoruz.

@model profilKisisellestirme.Models.kullanici

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/farbtastic.js")" type="text/javascript"></script>
<link href="@Url.Content("~/Content/farbtastic.css")" rel="stylesheet" type="text/css" />


 <script type="text/javascript" charset="utf-8">
     $(document).ready(function () {
         var f = $.farbtastic('#picker');
         var p = $('#picker').hide();
         var selected;
         $('.colorwell')
          .focus(function () {
              if (selected) {
                  $(selected).removeClass('colorwell-selected');
              }
              f.linkTo(this);
              p.show();
              $(selected = this).addClass('colorwell-selected');
          });

         $("input[name=bgPosition]").change(function () {
             var s = $(this).attr("checked");
             var b = $("body");
             if (s) {
                 b.css({ backgroundAttachment: 'scroll', backgroundRepeat: 'repeat repeat' });
             }
             else {
                 b.css({ backgroundAttachment: 'fixed', backgroundRepeat: 'no-repeat no-repeat' });
             }
         });

     });
 </script>

@using (Html.BeginForm("Edit","kullanici",FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    string strColor = "#5c87b2";

    if (!string.IsNullOrEmpty(Model.kisisel.bgColor))
    {
        strColor = Model.kisisel.bgColor;
    }

    string strPosition = "";

    if (!string.IsNullOrEmpty(Model.kisisel.bgPosition))
    {
        if (Model.kisisel.bgPosition.Contains("scroll"))
        {
            strPosition = "checked";
        }    
    }    
    
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>kullanici</legend>

        @Html.HiddenFor(model => model.id)

        <div class="editor-label">
            @Html.LabelFor(model => model.kullaniciAdi)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.kullaniciAdi)
            @Html.ValidationMessageFor(model => model.kullaniciAdi)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.eposta)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.eposta)
            @Html.ValidationMessageFor(model => model.eposta)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.sifre)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.sifre)
            @Html.ValidationMessageFor(model => model.sifre)
        </div>
        <hr />

        <div style="width:500px">

            <div class="editor-label">
                <strong>Kişiselleştirme</strong>
            </div>
            
            <div class="editor-label">Arka resmi</div>
            <div class="editor-field">
                <input type="file" name="bgImageFile"/>

                @if (!string.IsNullOrEmpty(Model.kisisel.bgImage))
                {
                    <br />
                    <a href="?bgClear=true"><strong>Arkaplanı kaldır</strong></a>                    
                }
                
                <input type="hidden" name="bgImage" value="@Model.kisisel.bgImage" />

                <p style="margin-top:10px;color:Gray">
                    Yükleyeceğiniz fotoğraf en fazla <strong>750kb</strong> ve uzantısı <strong>jpg, png</strong> olabilir.
                </p>
            </div>
            
            <div id="picker" style="float: right;"></div>
            <div class="editor-label">Arka plan rengi</div>
            <div class="editor-field">
                <input type="text" name="bgColor" class="colorwell" value="@strColor" />
            </div>

            <div class="editor-label">
            Arkaplan tekrar etsin <input type="checkbox" name="bgPosition" @strPosition />
            </div>

        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Son olarakda _Layout.cshtml içindeki tagını <body style=”@Session[“bgStyle”]”> şeklinde değiştiriyoruz.

Mekanızmanın mantığından biraz bahsetmek istiyorum. Öncelikle anlık renk değişimi ve arkaplanın pozisyonunu nasıl ayarladığımızdan bahsedeyim. Aslında bahsedecek çok fazlada bir şey yok, jQuery ile ilgili değişikliklerin olduğu form elemanlarını yakalayıp ilgili değişiklikleri sayfaya uyguluyoruz. Renk değişimini uygulamak içinse farbtastic.js içine 247. satıra $(“body”).css(“backgroundColor”,fb.color); kodunu ekliyoruz, diğer kodlar şu şekilde;

 $(document).ready(function () {
         var f = $.farbtastic('#picker');
         var p = $('#picker').hide();
         var selected;
         $('.colorwell')
          .focus(function () {
              if (selected) {
                  $(selected).removeClass('colorwell-selected');
              }
              f.linkTo(this);
              p.show();
              $(selected = this).addClass('colorwell-selected');
          });

         $(&quot;input[name=bgPosition]&quot;).change(function () {
             var s = $(this).attr(&quot;checked&quot;);
             var b = $(&quot;body&quot;);
             if (s) {
                 b.css({ backgroundAttachment: 'scroll', backgroundRepeat: 'repeat repeat' });
             }
             else {
                 b.css({ backgroundAttachment: 'fixed', backgroundRepeat: 'no-repeat no-repeat' });
             }
         });

     });

Geri kalan kısımda ise veritabanına bilgi ekliyoruz ve fotoğraf yüklüyoruz. Ben bu örnekte kullanıcının kişiselleştirilmiş style bilgisini Session da tuttum, kullanıcı sisteme giriş yaptığında bu bilgiyi güncellemek yeterli. Siz kendi yapınızda nasıl kullanmak istiyorsanız o şekilde kullanabilirsiniz. Projenin çalışır halini ve kodlarını incelediğinizde esasında olayın çok basit olduğunu fark edeceksiniz. Umarım faydalı bir yazı olmuştur :)

Uyarı: Bu mekanızma tamamen eğitsel amaçlıdır, kullanımdan doğacak güvenlik problemlerinden beni sorumlu tutmay

Projenin çalışır haline buradan bakabilir, buradan indirebilirsiniz.