Test Driven Development’a doğru

18 Haz

Programlamaya başlayan herkes, önce hiçbir kurala dikkat etmeden “Run” tuşuna basarak istediği sonucu görmek ister. Bu doğaldır çünkü öğrenmeye yeni başlayan bir programcı adayının tüm işleyiş hakkında detaylı bir bilgisi yoktur. Zaman ilerledikçe fonksiyon, metod, struct, class gibi yapıları öğrenmeye başlar. Öğrendiği yapıları severek uygulamr ve “Oh be ne rahatlık varmış” der. Artık uzun satırlar halinde yazıdığı karmaşık kodları sınıflara, metodlara bölerek yazmaya başlamıştır.

İşi biraz daha ilerleten programcımız daha önce hiç duymadığı bir kavram olan nesneye dayalı programlamayı (Object Oriented Programming) karşısında görür. Neyneya dayalı programlamanın temeli olan Encapsulation(Kapsam), Inheritence(Miraslama) ve Polimorphism(Çok biçimlilik) kavramlarını öğrenir ve “Meğer ben daha önceleri kod yazmıyormuşum.” der. Nesneye yönelik programlama, geliştirilen kodun dış dünya ile izolasyonunu sağlar ve kodda bazı kısıtlamalar yapmaya olanak sunar. Bu sayede yazılımcının geliştirdiği kodu kullanan diğer geliştiriciler, kendilerini ilgilendirmeyen mahrem kodları görmezler ve kafa karışıklığı yaşamazlar. Ayrıca görülmemesini istediğimiz algoritmalar varsa private erişim belirleyiciler ile dış dünyadan gizleyebilirler. Kısaca nesneye dayalı programlama, geliştirilen API üzerinde bazı kısıtlamalar yapmaya ve API içerisinde gerekli durumlarda miraslama ile hiyerarşik yapının kurulmasına olanak sağlanmış olur. Artık programcı, ikinci adım olan nesneye dayalı programlamayı da öğrenmiştir ve uygulamaya başlamıştır.

Bir süre sonra programcı, Test Driven Development(TDD) kavramıyla karşılaşır. Programcının kodlama geçmişine aykırı, kodlama mantığını ve kodlama biçimini kökten değiştirecek yeni bir akımdır bu. Alışılagelmiş şelale(Waterflow) tarzı kod geliştirmeyi reddeden, önce testin yazılmasını gerektiren ve testten başarıyla geçen konun düzenlenerek üretime katılmasını sağlayan bir yöntemdir. Programcı, TDD mantığını öğrendiğinde, ya onu çok sever ya da ondan nefret eder. Ortası yoktur bu işin. Çünkü kodun bir kısmı test edilebilir, bir kısmı teste uymayan şekilde yazıldığında çelişkiler yumağı oluşmaya başlar.

Genelde TDD iyi öğrenilmediği taktirde, saçma sapan bir iş olduğu düşünülerek terk edilir. Ama işin aslı öyle değildir. Sanılanın aksine TDD, çok gerekli ve yazılımın başarıya ulaşması için önemli bir yöntemdir.   Koda olan güveni arttırır. Başarılı sonuç almaya daha yatkın bir yöntemdir. Geleneksel yazılım yöntemleriyle başlatılan projelerin %50’den azının başarıya ulaştığı bir ortamda, denemeye değer bir yöntem olduğu açıktır.

Geleneksel yöntemlerle başarıya ulaşan projelerin sayısının az olmasının sebebi nedir? Sebeplerin en başında, ürünün sürekli gelişen bir yapıda olduğunun göz ardı edilmesi gelmektedir. Gelişim varsa değişimde vardır. Sürekli değişimin kaçınılmaz olduğu bir projede her şeyi önceden kestirilmeye çalışımak, sonu belli olmayan bir maceraya atılmak gibidir. Hal böyle olunca, yöntemde bir sorun olduğu ortaya çıkmaktadır.

Test edilmeyen kodların birbirini nasıl etkilediği, davranışlarının nasıl olduğu bilinmediğinden, zamanla kod kırlmaları yaşanmaya başlayar. Aslında geleneksel yöntemlerde de test işlemi yapılmaktadır. Ancak bu test işlemi, özel bir test geliştirme aracıyla değil yazılımcının geliştirdiği arayüzlerle v.s yapılmaktadır. TDD yönteminde ise kodların davranışları önce bir test aracından geçirilir, üretilen kodlar kullanıma hazır bir şeklide uygulama ortamına sunulmaktadır.

Bu arada test driven development ile geliştirme yapanlar, önce test yazıp sonra kod üretimi yapak zorunda da değildir. Kodu yazdıntan sonra da test sınıflarını yazanlar var. Ancak bu yöntem TDD geleneğine uygun bir yöntem değildir

Özetle test driven development, geleneksel yöntemlerin dışında bir tekniktir. Bu tekniğe alışmak biraz zordur. Çünkü bu yöntem sağ elimizle yapmaya alıştığımız işleri, sol elimizle yapmaya zorlar gibidir. Önce kodu yazıp sonra ara yüzümüzde test etmek yerine, önce testi yazıp sonra testten geçen kodları çalışan kod olarak kullanırız.

Bu yöntem çevik(agile) süreçlerin de önem kazandığı günümüzde çoğu yazılımcının gözdesi haline gelmiştir. Büyük yazılım şirketlerinin de vazgeliçmez yöntemidir.

Kendi Kendine Öğrenmeyi Öğrenmek

8 Haz

“İyi de bu bize öğretilmedi ki.” veya “Biz bu konuyu öğrenmedik ki.” cümlelerini çok fazla duymaya başladım. Hadi ilköğretim öğrencisi lise talebesi bunu söyler de üniversite öğrencisinden veya üniversite bitirmiş birinden bu lafları duymak çok sinir bozucu. Yani programlama  bilmiyorum diyene niye öğrenmiyorsun demek için kurmuyorum cümlelerimi. Öğrendiğin konularda neden kendini geliştirmek istemiyorsun. Ya da okulda verilen yazılım dersleriyle neye ulaşmaya uğraşıyorsun, ey genç yazılımcı. Peşin peşin söyleyeyim okul bilgilerinle çok fazla bir şey elde edemeyeceksin. Eğer bu söylediğimin tersi olsaydı mezun olan her yazılımcı her türlü yazılım projesinin altından kalkabilirdi. Web projesi, mobil projeler, işletim sistemleri, masaüstü yazılımlar, veritabanı yazılımları gibi her türlü projede söz söylemek mümkün olurdu bir yazılımcı için. Ama  durum çok farklı.

Kişi yürümek istediği yolu kendi seçmeli ve o yolda gerekli her türlü bilgiyi kendi öğrenmeli. Başarıya bu şeklide ulaşılır. Bana göre başarı hedeflediğine ulaşmaktır. Gözde meslekleri edinmek, ünlü üniversitelerde okumak değil. Bu yüzden, başarı için önce hedefin belirlenmesi gereklidir. Daha sonra hedefe giden yolda yılmadan yürümek gerek.

Eğer okulda öğretilenlerle büyük işler yapılabilseydi, Bill Gates’in okuduğu sınıftaki öğrenci sayısı kadar İşletim sistemi, Mark Zuckerberg’in sınıf arkadaşı kadar Facebook benzeri sosyal paylaşım sitesi, Larry Page’in sınıf arkadaşları kadar ünlü Google arama motoru olurdu. Ama durum farklı. Örneğin mühendislik okuduysanız, mezun olduğunuzda piyasaya sadece sınıf arkadaşlarınız kadar mühendis dahil oluyor. Mühendisliğinizi konuşturmak, fikirlerinizi hayata geçirmekte sizin elinizde, “biz bunları ögrmedik ki nasıl yapalım” diye söylenmekte. Karar sizin.

Kendimi nasıl geliştirmeliyim diye merak edenler için kendi alanımdan yol gösterebilirim. Diyelim ki yazılım alanındasınız ve uzman bir yazılımcı olmak istiyorsunuz. Seçtiğiniz alanla ilgili sektörün öncülerini takip ederek işe başlayabilirsiniz. Blog yazılarını, kitaplarını okuyarak veya videolarını izleyerek başlayabilirsiniz. Sektörün en iyi kaynak kitapları maalesef yurt dışında bulunmaktadır. Bu kitaplara internet aracılığıyla ulaşabilirsiniz. .NET veya Java alanında internette sayısız kitap bulunmakta. Bu kitaplarda gerçek hayat tecrübeleri de aktarılmaktadır. Okuduğum kitapları bir seri halinde blogda paylaşmak istiyorum. Vakit buldukça bunları da paylaşacağım.

İkinci adım ise öğrendiklerimizi uygulamak ve hayallerimizi gerçekleştirebileceğimiz bilgileri öğrenmek. Yani ben herşeyi öğreneyim, birgün lazım olur diyerek vakit kaybetmeyin. İş modelimizi geliştirmeli ve o modele uygun konuları öğrenmeliyiz. En önemlisi de bilgilerimizi hayallerimiz doğrultusunda kullanabilmek.

Son söz: Hayallerinizden korkmayın.

Asp.Net MVC Gzip/Deflate Sıkıştırılmış (Compressed) içerik

15 May

Web sayfalarımızın içeriği genişledikçe, sunucu tarafından oluşturulan cevapların(response) boyutu artmaktadır. Bu boyutu küçültmenin yolu içeriği sıkıştırmaktır.

Bu işlemi incelemek için senaryomuzda, içeriği binlerce kelimeden oluşan bir sunucu cevabı (response) oluşturup,  kullanıcı(client) tarafına sunalım. Bu işlemi önce normal bir şekilde, ardından da sıkıştırılmış bir şekilde gerçekleştirelim ve farkı görelim.

ASP.NET MVC ortamında çalıştığımız için önce bir action metod oluşturup içeriğini doldurarak sunalım ve boyutuna bakalım.


public ActionResult Zip()
{
     StringBuilder result = new StringBuilder();

     for (int i = 0; i < 42000; i++)
     {
          result.Append("word");
     }

     return Content(result.ToString());
}

Yukarıdaki action metod ile 42000 kelimeyi içeren bir içeriği kullanıcıya sunuyoruz. Bu içeriğin boyutuna Firefox tarayıcısında Firebug eklentisiyle bakalım.

Sıkıştırılmamış içerik

Evet içerin 164.1KB boyutunda oluşturulmuş durumda.

Şimdi bu işlemi, içeriği sıkıştırarak yapmayı deneyelim. Önce sıkıştırılacak action metod veya controller sınıfını sıkıştırmaya yarayan bir attribute oluşturalım. Daha sonra sıkıştırmak istediğimiz metodu bu attribute ile imzalayabiliriz.

public class CompressAttribute: ActionFilterAttribute
{
      public override void OnActionExecuting(ActionExecutingContext filterContext)
      {
          var encodingAccept = filterContext.HttpContext.Request.Headers["Accept-Encoding"];

          if (string.IsNullOrEmpty(encodingAccept))
              return;

          encodingAccept = encodingAccept.ToLowerInvariant();

          var response = filterContext.HttpContext.Response;

          if (encodingAccept.Contains("gzip"))
          {
              response.AddHeader("Content-encoding", "gzip");
              response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
          }
          else if (encodingAccept.Contains("deflate"))
          {
              response.AddHeader("Content-encoding", "deflate");
              response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
          }

      }

}

Şimdi oluşturduğumuz bu attribute ile metodumuzu imzalayıp tekrar içerik boyutuna bakalım.

[Compress]
public ActionResult Zip()
{
      StringBuilder result = new StringBuilder();

      for (int i = 0; i < 42000; i++)
      {
           result.Append("word");
      }

      return Content(result.ToString());
}

Gzip sıkıştırılmış içerik

İçerik 1.9KB boyutuna düştü. Sıkıştırma işleminden önceki içerik 164.1KB idi. Bence bu müthiş birşey.

Tekrar görüşmek ümidiyle…

ASP.NET MVC ile Dosya okuma ve yazma işlemleri

14 May

Web ortamında bazı durumlarda dosyalarla işlem gerektiren durumlar olabilmektedir. Örneğin bir HTML sayfa, CSS dosyası, Text dosya veya şu anda aklıma gelmeyen bir çeşit dosyanın içeriğinin online olarak değiştirilmesi gibi.

Bu işlemi, ASP.NET MVC ortamında nasıl gerçekleştirebileceğimizi inceleyelim. Bu işlem için dosyalarımızın bulunduğu bir dizini belirleyip içindeki dosyaları kullanıcının önüne döküp, istediği gibi düzenlemesini sağlamaya çalışalım.

Dizin içindeki dosyaları kullanıcıya veren bir model sınıfı oluşturalım.


public class PersonelFiles
{
      public string FileName { get; set; }
}

Bu model sınıfından üretilen bir view oluşturmak için File controller içerisine Files adında bir action metod oluşturalım.


public class FileController : Controller
{
      public ActionResult Files()
      {
         DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Files"));

         var personelFiles = new List<PersonelFiles>();

         foreach (var item in directory.GetFiles("*.txt"))
         {
             personelFiles.Add(new PersonelFiles { FileName = item.Name });
         }

         return View(personelFiles);
     }
}

Files dizinindeki *.txt uzantılı dosyalarımızı listeleyecek bir view artık bu action metod üzerinden oluşturulabilir. Files() action metoduna sağ tıklayıp create view diyerek ilerleyebiliriz.

Şimdi de dosyaların içeriğini editleme işlemini gerçekleştirmek için, düzenle linkine tıklandığında dosya içeriğini bir kutu içerisinde bize sunacak action metodu yazalım.

Metod adı Edit şeklinde olacaktır.


public ActionResult Edit(string id)
{
     if (!string.IsNullOrEmpty(id))
     {
         StreamReader reader = new StreamReader(Server.MapPath("~/Files/") + id, System.Text.Encoding.Default);

         var content = new FileEditFormView()
         {
             FileContent = reader.ReadToEnd(),
             FileName = id
         };

         reader.Close();
         reader.Dispose();

         return PartialView("_Edit", content);
     }

     return View("FileNotFound");

}

Edit modtodu, düzenle linkine tıkladığımızda linkteki id parametresiyle dosya adını Edit metoduna verecektir. dosya içeriği okundukran sonra  FileEditFormView şeklinde karşımıza gelecektir.

Kaydet butonuna bastığımızda da POST metodu ile gönderdiğimizde de yazma işlemini gerçekleştireceğiz.


[HttpPost]
public ActionResult Edit(FileEditFormView form)
{
      StreamWriter writer = new StreamWriter(Server.MapPath("~/Files/") + form.FileName, false, System.Text.Encoding.Default);

      writer.Write(form.FileContent);
      writer.Close();
      writer.Dispose();

      return RedirectToAction("Files");
}

Bu şekilde işlem tamamlanmış olacaktır.

Düzenleme Geçmişi:

Başlık düzenlendi 25.09.2013
İçerik düzenlendi 25.09.2013

C# Conditional ve Ternary Operatorler

14 May

Yazılım geliştiriciler olarak bazen kod ekonomisine başvurmak istediğimiz durumlar olabilmektedir. Özellikle de if şartlarını oluştururken parantez açıp kapatmak yerine sınama işlemini tek satırda yapabilmekteyiz.

if(){}else{} kodu yerine kısaca ?: operatörlerinin kullanımına bakalım.

Senaryomuz, mantıksal bir durum kontrolünün sınamasına göre string değer döndürecek bir iş akışının hazırlanması şeklinde olabilir.


     bool durumu = getDurum();

     string sonuc="";

     if (durumu)
     {
        sonuc = "Onaylanmış";
     }
     else
     {
        sonuc = "Beklemede";
     }

     Console.WriteLine(sonuc);

Yukarıda basitçe, durum değişkeninin true ve false olup olmadığı kontrol edilmektedir.

Bu işlemi kısaca ?: operatörüyle yaparsak şu şekilde olacaktır.

     bool durumu = getDurum();

     string sonuc = durumu ? "Onaylanmış" : "Beklemede";

     Console.WriteLine(sonuc);

Bu şekilde if ve else yapısı iptal edilerek tek satırda işlem tamamlanmaktadır. Bir başka yazım şekli ise şu şekildedir:

     string sonuc = durumu == true ? "Onaylanmış" : "Beklemede";

Yapı şu şekildedir:

     string sonuc = <mantıksal kontrol> ? <true ise dönen değer> : <false ise dönen değer>;

Tekrar görüşmek ümidiyle…

C# Extension Metod Tanımlama ve Kullanma

11 May

Programlama dillerinde varsayılan olarak gelen tiplere yapılan eklemelere, bir başka deyişle yamalara extension metod diyebiliriz. Bu yazıda, c# ile extension methodların nasıl tanımlandığını, nasıl uygulandığını  ve hangi mantıkla çalıştığını incelemeye çalışacağız.

C# dilinin temel tipleri olan int, string, double ve sayamadığım birçok tip, object tipinden türemiştir ve object tipinin özelliklerini taşımaktadır. Biz de bu özelliklerin yanında gerekli olan metodları bu tiplere ekleyebiliriz.

Örneğin şöyle bir senaryomuz olsun: string türündeki içerikler eğer belli bir karakterden uzunsa (…) şeklinde kısaltılsın.

Bunun için extension metodumuzu hazırlayalım. Extension metodun ulaşılabilmesi için bir static class içerisinde, static bir metod olarak tanımlanması gerekir.


public static class ExtensionString
{
     public static string Kisaltma(this string text, int maxSize)
     {
          return text.Length > maxSize ? text.Substring(0, maxSize).Insert(maxSize, "...") : text;
     }
}

Yukarıda görüldüğü üzere, ExtensionString adında static bir sınıf ve Kisaltma adında static bir metod oluşturuldu. Kisaltma metodu this string şeklinde bir parametre almaktadır. Bu demek oluyor ki Kisaltma metodu, string tipindeki değişkenlere eklenecek. Yani artık her string değişkeni, Kisaltma adında bir metoda sahip.

Burada dikkat edilmesi gereken, extension metodu barındıran sınıfın kullanılmak istenen yerden görünüyor olması gerekir. Yani gerekirse using ile sınıf içerisinde tanımlanmalıdır.


class Program
{
      static void Main(string[] args)
      {
         string baslik = "Bu yazının içeriği ne kadar uzunmuş böyle.";

         Console.WriteLine(baslik.Kisaltma(10));
      }

}

Ekran çıktısı

Kisaltma metoduile 10 karakterden sonra “…” şeklinde devam edilmektedir. Artık istediğimiz yerde bu metodu kullanabiliriz.

Esri Silverlight Api Query SpatialReference Problemi

11 May

Esri silverlight API kullananların yaşadıkları sorunlar dizisinden birisiyle daha karşı karşıya kalabilirsiniz. Bu sorun, harita üzerindeki bir yere sorgu yapmak istediğinizde karşımıza çıkıyor. Daha açık bir ifadeyle bir Query sonucunda sorgulanan bir yere harita züerinde çizim yapmak istediğimizde karşı karşıya kalabilmekteyiz. Örneğin bir şehir seçildiğinde o şehri harita üzerinde maviye boyamak istediğimizde sonuç alamayabiliriz.

Ben bu sorunu Esri Silverlight V2.4 dll ve Arcgis 10 Service yayınlarında yaşadım. Sorunun kaynağında yatan ise Query yapılan Layer ile Map Layer arasındaki SpatialReference farkıydı.

Sorgu:


private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
      QueryTask queryTask = new QueryTask("http://domain/ArcGIS/rest/services/sehirler/MapServer/0");

      queryTask.ExecuteCompleted += QueryTask_ExecuteCompleted;

      ESRI.ArcGIS.Client.Tasks.Query query = new ESRI.ArcGIS.Client.Tasks.Query();
      query.Where = "ILADI=" + "'Sample'";
      query.ReturnGeometry = true;
      query.OutFields.Add("*");
      queryTask.ExecuteAsync(query);

}

Map SpatialReference
Query SpatialReference

iki şekilde görüldüğü üzere sorgu yapılan Layer ve Map Layer arasında SpatialReference Farkı var. Bu farkı gidermek için sorguda kiük bir değişiklik yaparak SpatialReference farklılığını gideriyoruz.

private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{

       QueryTask queryTask = new QueryTask("http://domain/ArcGIS/rest/services/sehirler/MapServer/0");

       queryTask.ExecuteCompleted += QueryTask_ExecuteCompleted;

       ESRI.ArcGIS.Client.Tasks.Query query = new ESRI.ArcGIS.Client.Tasks.Query();
       query.Where = "ILADI=" + "'Sample'";
       query.ReturnGeometry = true;
       query.OutFields.Add("*");
       query.OutSpatialReference = MyMap.SpatialReference;
       queryTask.ExecuteAsync(query);

}

Bu işlemin ardından iki Spatial referans eşitlenir ve sorun ortadan kalkar. Map üzerindeki GraphicsLayer zerinde yapılmak istenen çizim işlemi de gerçekleşir.

GraphicsLayer

Eğer SpatialReference eşitlemesi yapılmasaydı, koordnat sistemi farkları yüzünden bu çizim işlemi başarısız olacaktı.

ASP.NET MVC Reset Password

7 May

Bir çok web sitesinin klasik bölümüdür şifremi unuttum bölümü. Kullanıcı adınızı veya email adresinizi girersiniz ve mail adresinize postalanır yeni şifreniz. Peki bu senaryo ASP.NET  MVC ile Membership yapısı kullanılarak nasıl yapılır? Yani kullanıcı şifresi resetlenir (reset password) ve yeni şifre mail olarak gönderilir.

Bu işlem için önce sistemimizin konfigurasyonunu mail gönderebilecek şekilde hazırlamamız gerekmektedir.


<system.net>
    <mailSettings>
       <smtp deliveryMethod="Network">
         <network host="mailhostadresiniz" (örneğin smtp.gmail.com)
                  port="587"
                  userName="emailadresiniz"
                  password="sifreniz"
                  enableSsl="true"/> (SSL gerektiren mail sunucu kullanıyorsanız)

       </smtp>
    </mailSettings>
</system.net>

Sistemimiz mail gönderemeye hazır bir vaziyete gelmiş durumda.

ASP.NET MVC projemizde Models dizinindeki Account model içerisine yeni bir model tanımlamalıyız. Bu modelin adı LostPasswordModel olacak.


public class LostPasswordModel
{
     [Required(ErrorMessage = "Kullanıcı adınızı giriniz.")]
     [Display(Name="Kullanıcı Adı")]
     public string Username { get; set; }
}

Bu model ile kullanıcıdan kullanıcı adını talep ederek mail adresine yeni şifresini göndereceğiz.

Bu modelden gelen kullanıcı adını alarak o kullanıcının şifresini sıfırlayıp, yeni mail adresine postalamalıyız. Bu işlemi yapmak için aşağıdaki metodu tanımlayabiliriz.

public void ResetPassword(string username)
{

     MembershipUser user = Membership.GetUser(username);

     string confirmationGuid = user.ProviderUserKey.ToString();
     string newPassword = user.ResetPassword();
     string bodyMessage = string.Format("Yeni Şifreniz {0}",newPassword);

     var message = new System.Net.Mail.MailMessage("kimden@mail.com", user.Email)
     {
         Subject = "Yeni şifre oluşturma isteği.",
         Body = bodyMessage
     };

     var client = new System.Net.Mail.SmtpClient();
         client.Send(message);
}

Bu metod sayesinde kullanıcının mail adresine yeni şifresini postalamış olduk.

ASP.NET MVC Email Doğrulama (Verification)

6 May

ASP.NET üyelik sistemlerinde bir gelenek olan üyelerin email adreslerini doğrulama işleminden bahsedelim birazda. Sistemimize üye olanları email adresleri aracılığıyla gerçek kullanıcı olup olmadıklarını anlayabiliriz bu sayede. Bu işlem için sistemin konfigurasyonlarının mail gönderebilecek hale getirilmesi gerek. Yani mail ayarları yapılmalıdır.


<system.net>
   <mailSettings>
      <smtp deliveryMethod="Network">
           <network host="mailhostadresiniz" (örneğin smtp.gmail.com)
                    port="587"
                    userName="emailadresiniz"
                    password="sifreniz"
                    enableSsl="true"/> (SSL gerektiren mail sunucu kullanıyorsanız)
      </smtp>
   </mailSettings>
</system.net>

Bu ayarlar yapıldıktan sonra üyelerin kayıtlarının yapıldığı sırada bir doğrulama postasının otomatik olarak gönderilmesi gerekir. Bu işlemi yapan metodu hazırlamalıyız.


public void SendConfirmationEmail(string username)
{

      MembershipUser user = Membership.GetUser(username);

      string confirmationGuid = user.ProviderUserKey.ToString();
      string verifyUrl = System.Web.HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) +
                         "/Account/Verify?Id=" +
                         confirmationGuid;

      string bodyMessage = string.Format("üyeliğiniz başarıyla oluşturulmuştur. Aşağıdaki linke tıkladığınızda hesabınızın aktif olacaktır.\n");
             bodyMessage += verifyUrl;

      var message = new System.Net.Mail.MailMessage(Models.Configuration.SystemMail, user.Email)
      {
          Subject = "Üyeliğinizi doğrulayın.",
          Body = bodyMessage
      };

     var client = new System.Net.Mail.SmtpClient();
         client.Send(message);

}

Mail gönderen metodumuz da artık hazır olduğuna göre bu metodu kayıt işlemi sırasında kullanabiliriz.


[HttpPost]
public ActionResult Register(RegisterModel model)
{

   if (ModelState.IsValid)
   {
       MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email, false);

       if (createStatus == MembershipCreateStatus.Success)
       {
            SendConfirmationEmail(model.UserName);

            return RedirectToAction("Confirmation","Account");
       }
       else
       {
            ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
       }

    }

    return View(model);

}

Artık kayıt olan üyelere otomatik olarak mail gönderiliyor.

Bu linke tıklandığında, üye Account controller içindeki Verify action metoduna yönlendirilecektir.


public ActionResult Verify(string Id)
{
     MembershipUser user = Membership.GetUser(new Guid(Id));

     user.IsApproved = true;
     Membership.UpdateUser(user);

     return RedirectToAction("Welcome");
}

Bu action metod sayesinde linke tıklayan üyenin üyeliği aktif hale getirilmiş oldu.

ASP.NET MVC Ajax.ActionLink ile sayfa yenilemeye son

30 Nis

İnternet sayfalarında artık yeni teknolojilerle birlikte javascript’in gücü iyice gösterilmeye başlandı. Sayfa yenilemeleri yapmak yerine sadece javascript ile sayfa üzerindeki etiketler(div) güncellenmekte. Linklere, butonlara tıklandığında istenen sonuçlar etkili bir biçimde bizi rahatsız etmeden önümüze dökülmekte. Son zamanlarda özellikle sosyal paylaşım sitelerinde javascript kendini o kadar belli ediyor ki, javascript’i icat edenler bile birgün bu kadar kullanılacağını tahmin etmemiştir.

Lafı fazla uzatmadan javascript özelliğini, liklere tıklandığında sayfa yenilemesi yapmadan önümüze getiren özelliği ASP.NET MVC mimarisinde kullanmaya çalışacağız.

Bir restorantın menü listesini önümüze getiren bir senaryomuz olduğunu varsayalım. Menü listesinde ürün adı ve fiyatı olsun. Bu yapıyı temsilen bir Menu adında sınıf oluşturmalıyız.


public class Menu
{
      public int Id { get; set; }
      public string Name { get; set; }
      public decimal Price { get; set; }
}

Şimdi MenuController adında bir controller sınıfı oluşturup bu controller sınıfının Index metodu ve Index view sayfası oluşturalım.


public class MenuController : Controller
{
      List<Menu> menu = new List<Menu>
      {
           new Menu{Id =1, Name="Hamburger", Price=3.15M},
           new Menu{Id =2, Name="Cheeseburger", Price=4.05M},
           new Menu{Id =3, Name="Cola", Price=2.0M},
           new Menu{Id =4, Name="Cips", Price=1.25M},
      };

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

      public ActionResult GetMenu()
      {
           return PartialView("_MenuPart", menu);
      }

}

Menu Listesi linkine tıklandığında sayfa yenilenmeksizin yukardaki liste tablo halinde linkin aldına indirilacek.

Bunun için yapılacak hazırlıklardan biri jquery.unobtrusive-ajax.min.js dosyasının view sayfasına referans edilmesi gerekmektedir. Aksi taktirde yaptığımız işlem çalışmayacaktır. Bu söylediklerim ASP.NET MVC3 için geçerli tabiki.

Referans olarak ana Layout sayfasına ekliyorum javascript dosyasını.

Şimdi Index view sayfası içine “Menu Listesi” linkini oluşturmalıyız.


@Ajax.ActionLink("Menu Listesi",
                 "GetMenu",
                 new AjaxOptions{
                                 InsertionMode=InsertionMode.Replace,
                                 UpdateTargetId="MenuBox",
                                 HttpMethod="GET",

                 })

<div id="MenuBox"></div>

Ajax helper sınıfının ActionLink Extension metodu ile link oluşturma işlemini gerçekleştirebiliriz. Bu metodun aldığı AjaxOptions parametresinde belirtilen, InsertionMode özelliği Replace olarak işaretlenir. Bu sayede işlem sonrasında, yani GetMenu metodundan dönen değeri UpdateTargerId parametresindeki html element içeriği ile değiştirileceğini belirtiyoruz.

Örneğimizde GetMenu metodu bir _MenuPart adında bir PartialView döndürüyor.

_MenuPart partial view içeriği ise şu şeklide olacaktır.


<table>
    <tr>
         <th>Name</th>
         <th>Price</th>
         <th></th>
    </tr>
    @foreach (var item in Model) {
    <tr>
        <td>@Html.DisplayFor(modelItem => item.Name)</td>
        <td>@Html.DisplayFor(modelItem => item.Price)</td>
        <td>@Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Details", "Details", new { id=item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
       </td>
    </tr>
    }

</table>

Sonuç olarak Index sayfasındaki Menu Listesi linkine tıklandığında bu tablo önümüze gelecek.