Skip to content

5. Görünüm ve şablonu

5.1. Introduction

ASP.NET MVC uygulamasının mimarisine geri dönelim:

Bir önceki bölümde, ASP.NET MVC'in, [1] sorgusundaki bilgileri, [2a] eylemine, doğrulama kısıtlamaları içerebilen bir şablon biçiminde nasıl sunduğunu inceledik. Bu şablon, eyleme girdi olarak sağlanıyordu ve biz buna eylem şablonu adını verdik. Şimdi, bir eylemin en yaygın sonucuna, yani bir V görünümü [3] ile birlikte onun M modeli [2c]'i içeren [ViewResult] türüne odaklanacağız. Bu modele V görünüm modeli denecektir; az önce incelediğimiz eylem modeliyle karıştırılmamalıdır. Biri eylemin girişinde, diğeri ise çıkışındadır.

Öncelikle, yine aynı çözümün içinde, temel ASP.NET MVC türünde yeni bir proje olan [Exemple-03] [1]'i oluşturalım:

[First] [2] adlı bir denetleyici oluşturalım. Bu denetleyici için oluşturulan kod şöyledir:


using System.Web.Mvc;

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

  }
}
  • 7-10. satırlar: bir [Index] eylemi oluşturulmuştur. [Index] yönteminin sonucunun türü, bir eylemin olası sonuçlarının çoğunun türetildiği [ActionResult] sınıfının türüdür;
  • 9. satır: [Controller] sınıfının (5. satır) [View] yöntemi, [ActionResult]'ten türetilen [ViewResult] türünü döndürür. Bu yöntem birçok aşırı yüklemeyi destekler. Bunlardan birkaçına göz atacağız. En önemlisi şudur:
 
  • ilk parametre, görünümün adıdır. Bu parametre yoksa, [ViewResult]'i üreten eylemle aynı adı taşıyan görünüm kullanılır ve bu görünüm, {controller}'ın denetleyici adı olduğu [/Views/{controller}] klasöründe aranır;
  • ikinci parametre ise görünümün şablonudur. Bu parametre eksikse, görünümün bir şablonu yoktur.

Aşağıdaki [Index] yöntemi:


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

[/Views/First/Index.cshtml] görünümünün görüntülenmesini ister. Bu yöntem, görünüme herhangi bir şablon aktarmaz. [1] dosyasını [/Views/First] klasöründe oluşturalım:

ardından bunun içinde [Index] [2] görünümünü oluşturalım:

Görünümün adını [3] olarak belirtin. Bu görünüm, [4] olarak oluşturulur. Oluşturulan kod şöyledir:


@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        
    </div>
</body>
</html>

Burada, 1-3. satırlar C# kodu olması dışında klasik bir HTML örneği vardır. Görünümleri yöneten programa görünüm motoru denir. Bu motor, HTML formatında olmayan her şeyi yöneterek bunları HTML formatına dönüştürür. Sonuçta, müşteriye gönderilecek olan da budur. Buradaki görünüm motorunun adı [Razor]'tir. Bu motor, bir görünüme C# kodu eklemeye olanak tanır. [Razor], bu C# kodunu yorumlayarak ondan HTML kodunu üretir. Bir görünüme C# kodu eklemek için bazı temel kurallar şunlardır:

  • HTML'ten C#'a geçiş, @ karakteriyle karşılaşıldığında gerçekleşir (1. satır). Bu karakter bir kod bloğunu başlatıyorsa, küme parantezleri (1. ve 3. satırlar) eklenir. Değerini almak istediğimiz bir değişkeni başlatıyorsa, sadece @değişken yazılır;
  • C#'dan HTML'e geçiş, < karakteriyle karşılaşıldığında (5. satır) gerçekleşir. Bazen, özellikle sayfaya HTML etiketleri içermeyen düz metin eklediğimizde bu dönüşümü zorlamak zorunda kalırız. Bu durumda metni eklemek için <text> etiketini kullanırız: <text>burada düz metin</text>.

Yukarıdaki 2. satır, [Index] görünümünün ana sayfası olmadığını gösterir.

Görünümü şu şekilde değiştirelim:


@{
  Layout = null;
  string vue = "Index";
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Index</title>
</head>
<body>
  <div>
    <h3>Vue @vue</h3>
  </div>
</body>
</html>
  • 3. satır: bir C# değişkeni tanımlar;
  • 15. satır: bu değişkenin değerini görüntüler.

Şimdi URL ve [/First/Index]'i çağıralım:

 

Alınan HTML kodu şöyledir:

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Index</title>
</head>
<body>
  <div>
    <h3>Vue Index</h3>
  </div>
</body>
</html>

Bu, tamamen HTML formatında bir belgedir. C# kodları tamamen ortadan kalkmıştır.

5.2. Bilgileri görünüme aktarmak için [ViewBag]'i kullanın

[Action01.cshtml] görünümüne bağlı, [Action01] adlı yeni bir eylem oluşturuyoruz:

[Action01] eylemi şu şekildedir:


    // Eylem01
    public ViewResult Action01()
    {
      ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
      return View();
}
  • 4. satır: Denetleyicinin [ViewBag] özelliği kullanılır. Bu, 4. satırda yapıldığı gibi özellikler eklenebilen dinamik bir nesnedir. Bu nesnenin özelliği, görünüm tarafından da erişilebilir olmasıdır. Dolayısıyla bu, nesneye bilgi aktarmanın bir yoludur;
  • 5. satır: Eylemin varsayılan görünümü istenir. Bu, [/First/Action01.cshtml] görünümüdür. Bu görünüme herhangi bir şablon aktarılmaz.

[Action01.cshtml] görünümü şöyledir:


@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action01</title>
</head>
<body>
  <div>
    <h4>@ViewBag.info</h4>
  </div>
</body>
</html>
  • 14. satır: [ViewBag.info] özelliği görüntülenir.

Test edelim. URL ve [/First/Action01]'i sorguluyoruz:

 

5.3. Görüneye bilgi aktarmak için güçlü tipli bir şablon kullanma

Önceki yöntemin dezavantajı, yürütme öncesinde hata tespitine izin vermemesidir. Dolayısıyla, [Action01.cshtml] görünümü şu kodu kullanıyorsa


<h4>@ViewBag.Info</h4>

kullanırsa, [Info] özelliği mevcut olmadığı için bir hata oluşur. [Action01] eylemi tarafından oluşturulan özellik ise [info] adını taşır. Bu sorunu önlemek için güçlü tiplemeli bir şablon kullanılabilir.

Daha önce incelenen örneklerden birinde eylem şöyleydi:


    // Eylem10
    public ContentResult Action10(ActionModel03 modèle)
    {
      string erreurs = getErrorMessagesFor(ModelState);
      string texte = string.Format("email={0}, jour={1}, info1={2}, info2={3}, info3={4}, erreurs={5}",
        modèle.Email, modèle.Jour, modèle.Info1, modèle.Info2, modèle.Info3, erreurs);
      return Content(texte, "text/plain", Encoding.UTF8);
}

[Action10] eylemi, müşterisine altı bilgiyi (E-posta, Gün, Bilgi1, Bilgi2, Bilgi3, hatalar) bir karakter dizisi biçiminde iletiyordu. Bu bilgileri [ViewModel01] görünüm modelinde aktaracağız. Bu model, [ActionModel03]'ten bilgileri devraldığı için, onu bu sınıftan türeteceğiz.

Öncelikle, [Exemple-02] projesinden [ActionModel03]'i mevcut [Exemple-03] projesine kopyalıyoruz:

ve ad alanını [Exemple-03] projesininkiyle aynı olacak şekilde değiştiriyoruz:


using System.ComponentModel.DataAnnotations;
namespace Exemple_03.Models
{
  public class ActionModel03
  {
    [Required(ErrorMessage = "Le paramètre email est requis")]
    [EmailAddress(ErrorMessage = "Le paramètre email n'a pas un format valide")]
    public string Email { get; set; }

    [Required(ErrorMessage = "Le paramètre jour est requis")]
    [RegularExpression(@"^\d{1,2}$", ErrorMessage = "Le paramètre jour doit avoir 1 ou 2 chiffres")]
    public string Jour { get; set; }

    [Required(ErrorMessage = "Le paramètre info1 est requis")]
    [MaxLength(4, ErrorMessage = "Le paramètre info1 ne peut avoir plus de 4 caractères")]
    public string Info1 { get; set; }

    [Required(ErrorMessage = "Le paramètre info2 est requis")]
    [MinLength(2, ErrorMessage = "Le paramètre info2 ne peut avoir moins de 2 caractères")]
    public string Info2 { get; set; }

    [Required(ErrorMessage = "Le paramètre info3 est requis")]
    [MinLength(4, ErrorMessage = "Le paramètre info3 doit avoir 4 caractères exactement")]
    [MaxLength(4, ErrorMessage = "Le paramètre info3 doit avoir 4 caractères exactement")]
    public string Info3 { get; set; }
  }
}
  • 2. satır: yeni ad alanı;

Ardından [ViewModel01] sınıfını oluşturuyoruz:

[ViewModel01] sınıfının kodu şöyledir:


namespace Exemple_03.Models
{
  public class ViewModel01 : ActionModel03
  {
    public string Erreurs { get; set; }
  }
}
  • 3. satır: Sınıf, [ActionModel03]'ten miras alır ve dolayısıyla [Email, Jour, Info1, Info2, Info3] özelliklerini de devralır;
  • 5. satır: Sınıf, [Erreurs] özelliğini de kazanır.

Şimdi, aşağıdakileri yapan [Action02] eylemini yazıyoruz:

  • giriş olarak [ActionModel03] eylem şablonunu kabul eder;
  • ve çıkış olarak [ViewModel01] görünüm şablonunu verir.

Kodu şu şekildedir:


    // Eylem02
    public ViewResult Action02(ActionModel03 modèle)
    {
      string erreurs = getErrorMessagesFor(ModelState);
      return View(new ViewModel01(){Email=modèle.Email, Jour=modèle.Jour, Info1=modèle.Info1, Info2=modèle.Info2, Info3=modèle.Info3, Erreurs=erreurs});
}
  • 1. satır: [Action02], [ActionModel03] eylem modelini alır. [ViewResult] türünde bir sonuç döndürür;
  • 4. satır: [ActionModel03] eylem şablonuyla ilgili hatalar, [erreurs] karakter dizisinde toplanır. [getErrorMessagesFor] yöntemi 65. sayfada açıklanmış ve yeni projenin [First] denetleyicisine eklenmiştir;
  • 5. satır: [View] yöntemi bir parametre ile çağrılır. Bu parametre, görünüm şablonudur. Görünüm şablonu belirtilmemiştir. Dolayısıyla, varsayılan [/Views/First/Action02] görünümü kullanılacaktır. [ViewModel01] görünüm modeli, [ActionModel03] eylem modelinden gelen beş bilgi ve 4. satırda oluşturulan [erreurs] bilgisiyle örneklenir ve başlatılır.

Şimdi [/First/Action02.cshtml] görünümünü oluşturuyoruz:

Kodu şu şekildedir:


@model Exemple_03.Models.ViewModel01
@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action02</title>
</head>
<body>
  <h3>Informations du modèle de vue</h3>
  <ul>
    <li>Email : @Model.Email</li>
    <li>Jour : @Model.Jour</li>
    <li>Info1 : @Model.Info1</li>
    <li>Info2 : @Model.Info2</li>
    <li>Info3 : @Model.Info3</li>
    <li>Erreurs : @Model.Erreurs</li>
  </ul>
</body>
</html>
  • Yenilik 1. satırda yer almaktadır. [@model] notasyonu, görünüm şablonunun türünü belirler. Bu şablon daha sonra [@Model] notasyonu ile referanslandırılır (16-21. satırlar);
  • 15-22. satırlar: model bilgileri bir listede görüntülenir.

[Action02] eyleminin yürütülmesine ilişkin birkaç örneği inceleyelim.

Öncelikle parametre olmadan:

 

ardından yanlış parametrelerle:

ardından doğru parametrelerle:

Bu örnekte, [ViewModel01] görünüm şablonu, [ActionModel03] eylem şablonundaki bilgileri devralır. Bu durum sıklıkla görülür. Böylece, hem eylem hem de görünüm şablonu olarak kullanılacak tek bir şablon kullanılabilir. Yeni bir [ActionModel04] şablonu oluşturuyoruz:

  

ve içeriği şu şekilde olacaktır:


using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace Exemple_03.Models
{
  [Bind(Exclude="Erreurs")]
  public class ActionModel04
  {
    // ---------------------- Eylem --------------------------------
    [Required(ErrorMessage = "Le paramètre email est requis")]
    [EmailAddress(ErrorMessage = "Le paramètre email n'a pas un format valide")]
    public string Email { get; set; }

    [Required(ErrorMessage = "Le paramètre jour est requis")]
    [RegularExpression(@"^\d{1,2}$", ErrorMessage = "Le paramètre jour doit avoir 1 ou 2 chiffres")]
    public string Jour { get; set; }

    [Required(ErrorMessage = "Le paramètre info1 est requis")]
    [MaxLength(4, ErrorMessage = "Le paramètre info1 ne peut avoir plus de 4 caractères")]
    public string Info1 { get; set; }

    [Required(ErrorMessage = "Le paramètre info2 est requis")]
    [MinLength(2, ErrorMessage = "Le paramètre info2 ne peut avoir moins de 2 caractères")]
    public string Info2 { get; set; }

    [Required(ErrorMessage = "Le paramètre info3 est requis")]
    [MinLength(4, ErrorMessage = "Le paramètre info3 doit avoir 4 caractères exactement")]
    [MaxLength(4, ErrorMessage = "Le paramètre info3 doit avoir 4 caractères exactement")]
    public string Info3 { get; set; }

    // ---------------------- görünüm --------------------------------
    public string Erreurs { get; set; }
  }
}
  • 8-28. satırlar: bütünlük kısıtlamalarıyla birlikte eylem modeli. Bu alanlar aynı zamanda görünümün de bir parçası olacaktır;
  • 31. satır: Görünüm modeline özgü bir özellik. Bu özellik, 5. satırdaki açıklama sayesinde eylem modelinden hariç tutulmuştur.

Aşağıdaki yeni [Action03] eylemini oluşturuyoruz:


    // Eylem03
    public ViewResult Action03(ActionModel04 modèle)
    {
      modèle.Erreurs = getErrorMessagesFor(ModelState);
      return View(modèle);
}
  • 2. satır: [Action03], [ActionModel04] türündeki eylem modelini alır;
  • 5. satır: ve aynı şablonu görünüm şablonu olarak döndürür;
  • satır 4: [Erreurs] bilgisiyle tamamlanır;

Geriye sadece [/First/Action03.cshtml] görünümünü oluşturmak kalıyor:

  • [1] olarak: [Action03] koduna sağ tıklayın, ardından [Ajouter une vue];
  • [2]'e: varsayılan olarak önerilen görünüm adı;
  • [3]'te: güçlü tipli bir görünüm oluşturulduğunu belirtin;
  • [4]'te: açılır listeden doğru sınıfı seçin, burada [ActionModel04] sınıfı;
  • [5]: oluşturulan görünüm.

[Action03] görünümüne, [Action02] görünümündekiyle aynı kodu veriyoruz. Yalnızca görünüm şablonu (1. satır) ve sayfa başlığı (11. satır) değişiyor:


@model Exemple_03.Models.ActionModel04
@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action03</title>
</head>
<body>
  <h3>Informations du modèle de vue</h3>
  <ul>
    <li>Email : @Model.Email</li>
    <li>Jour : @Model.Jour</li>
    <li>Info1 : @Model.Info1</li>
    <li>Info2 : @Model.Info2</li>
    <li>Info3 : @Model.Info3</li>
    <li>Erreurs : @Model.Erreurs</li>
  </ul>
</body>
</html>

Şimdi [Action03] eylemini parametre olmadan çağıralım:

 

Sonuçlar öncekiyle aynıdır. Eylem ve görünüm için aynı şablonun kullanılması yaygın bir uygulamadır, çünkü görünüm şablonu genellikle eylem şablonundaki bilgileri alır. Bu durumda, hem eylem hem de eylemin oluşturduğu görünüm tarafından kullanılabilen daha kapsamlı bir şablon kullanılır. Eylem modeline ait olmayan bilgilerin veri bağlamasından hariç tutulmasına özen gösterilmelidir. Aksi takdirde, bilgili bir kullanıcı, bizim haberimiz olmadan görünüm modelinin bazı kısımlarını başlatabilir.

5.4. [Razor] – ilk adımlar

Şimdi [Razor] görünümlerinin bazı öğelerini, özellikle de foreach ve if komutlarını tanıtacağız.

HTML tablosunda bir kişi listesi sunmak istediğimizi varsayalım. Görünüm şablonu şu şekilde olabilir: [ViewModel02]:


namespace Exemple_03.Models
{
  public class ViewModel02
  {
    public Personne[] Personnes { get; set; }
    public ViewModel02()
    {
      Personnes = new Personne[] { new Personne { Nom = "Pierre", Age = 44 }, new Personne { Nom = "Pauline", Age = 12 } };
    }
  }

  public class Personne
  {
    public string Nom { get; set; }
    public int Age { get; set; }
  }
}
  • modelin görünümü, 3-10. satırları kapsayan [ViewModel02] sınıfıdır;
  • 5. satır: model, 12-16. satırlarda tanımlanan [Personne] türünde bir kişi dizisine sahiptir;
  • 6-10. satırlar: Model oluşturucu, 5. satırdaki [Personnes] özelliğini iki kişiden oluşan bir dizi ile başlatır.

Bu modeli çıktı olarak üreten eylem şu şekilde olacaktır: [Action04]:


    // Eylem04
    public ViewResult Action04()
    {
      return View(new ViewModel02());
}
  • 2. satır: eylemin giriş modeli yoktur;
  • 4. satır: Eylem, varsayılan görünümüne, yani az önce tanımladığımız [ViewModel02] modelinin bir örneğine geçer.

[Action04.cshtml] görünümü, [ViewModel02] modelini görüntüleyecektir:

[Action04.cshtml] görünümünün kodu şöyledir:


@model Exemple_03.Models.ViewModel02
@using Exemple_03.Models

@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action04</title>
</head>
<body>
  <table border="1">
    <thead>
      <tr>
        <th>Nom</th>
        <th>Age</th>
      </tr>
    </thead>
    <tbody>
      @foreach (Personne p in Model.Personnes)
      {
        <tr>
          <td>@p.Nom</td>
          <td>@p.Age</td>
        </tr>
      }
    </tbody>
  </table>
</body>
</html>
  • 1. satır: görünüm şablonu;
  • 2. satır: 24. satırda kullanılan [Personne] sınıfının ad alanının içe aktarımı;
  • 16-32. satırlar: modeldeki kişileri görüntüleyen HTML dizisi;
  • 24. satır: C# kodunun başlangıcı @ karakteriyle belirtilir. [foreach] komutu, modeldeki tüm kişileri döngüye alır;
  • 26-27. satırlar: < karakteri C#'ı sonlandırır ve HTML'i başlatır. Ardından tekrar @ karakteri ile C# moduna geçilir ve kişinin adı yazılır. Sonra tekrar < karakteri ile HTML moduna geçilir;
  • 28. satır: Kişinin yaşı yazılır.

[Action04] eyleminin yürütülmesi şu sonucu verir:

 

Bir görünümdeki diğer öğeler de bir koleksiyondan beslenebilir: açılır menüler (açılır olsun ya da olmasın), radyo düğmeleri, onay kutuları. Aşağıdaki yeni örneği ele alalım; bu örnekte bir açılır menü görüntülenmektedir.

[ViewModel05] şablonu şu şekilde olacaktır:


namespace Exemple_03.Models
{
  public class ViewModel05
  {
    public Personne2[] Personnes { get; set; }
    public int SelectedId { get; set; }

    public ViewModel05()
    {
      Personnes = new Personne2[] { 
        new Personne2 { Id = 1, Prénom = "Pierre", Nom = "Martino" }, 
        new Personne2 { Id = 2, Prénom = "Pauline", Nom = "Pereiro" }, 
        new Personne2 { Id = 3, Prénom = "Jacques", Nom = "Alfonso" } };
      SelectedId = 2;
    }
  }

  public class Personne2
  {
    public int Id { get; set; }
    public string Nom { get; set; }
    public string Prénom { get; set; }
  }
}
  • 18. satır: üç özelliğe sahip bir [Personne2] sınıfı;
  • 3. satır: görünümün [ViewModel05] şablonu;
  • 5. satır: açılır listede görüntülenecek kişilerin listesi, [Prénom Nom] biçiminde;
  • 6. satır: açılır listeden seçilecek kişinin [Id]'i;
  • satır 8-16: Üç kişilik bir tablo oluşturan (satır 10-13) ve seçili olarak görünmesi gereken kişinin [Id] değerini belirleyen oluşturucu.

[Action05.cshtml] görünümü bu şablonu gösterecektir:

Kodu şu şekildedir:


@model Exemple_03.Models.ViewModel05
@using Exemple_03.Models

@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action05</title>
</head>
<body>
  <select>
    @foreach (Personne2 p in Model.Personnes)
    {
      string selected = "";
      if (p.Id == Model.SelectedId)
      {
        selected = "selected=\"selected\"";
      }
      <option value="@p.Id" @selected>@p.Prénom @p.Nom</option>
    }
  </select>
</body>
</html>

HTML açılır listesinin özellikleri 2.5.2.6. paragrafında açıklanmıştır. Bunları tekrar hatırlatalım:

Açılır menü
<select size="1" name="cmbValeurs">
<option value="1">seçenek1</option>
<option selected="selected" value="2">seçenek2</option>
<option value="3">seçenek3</option>
</select>
 
HTML etiketi
<select size=".." name="..">
<option [selected="selected"] value=”v”>...</option>
...
</select>
<option>...</option> etiketleri arasında yer alan metinleri bir liste halinde görüntüler
öznitelikleri
name="cmbValeurs": denetimin adı.
size="1": görünür liste öğelerinin sayısı. size="1", listeyi bir açılır kutuya eşdeğer hale getirir.
selected="selected": Bir liste öğesi için bu anahtar kelime varsa, söz konusu öğe listede seçili olarak görünür. Yukarıdaki örneğimizde, choix2 liste öğesi, açılır menü ilk kez görüntülendiğinde seçili öğe olarak görünür.
value=”v”: öğe kullanıcı tarafından seçildiğinde, sunucuya gönderilen değer [v] olur. Bu öznitelik yoksa, sunucuya gönderilen değer görüntülenen ve seçili metin olur.

17-25. satırlardaki kod, 16. satırdaki <select> etiketinin içine yerleştirilen <option> etiketlerini oluşturur.

  • 17. satır: şablondaki kişi listesi taranır;
  • 20. satır: Geçerli kişinin seçilmesi gereken kişi olup olmadığı kontrol edilir. Eğer öyleyse, <option> etiketine eklenecek olan selected="selected" metni hazırlanır;
  • 24. satır: <option> etiketi yazılır.

[Action05] eylemini çağıralım:

  • [1,2]'te kişiler [Prénom Nom] biçiminde görüntülenir;
  • [1,2]'te, seçilen kişi [Id] değeri 2 olan kişidir.

Şimdi yukarıdaki sayfanın HTML kaynak kodunu inceleyelim:


<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action05</title>
</head>
<body>
  <select>
      <option value="1" >Pierre Martino</option>
      <option value="2" selected=&quot;selected&quot;>Pauline Pereiro</option>
      <option value="3" >Jacques Alfonso</option>
  </select>
</body>
</html>
  • 10-12. satırlar: [Razor] kodu tarafından oluşturulan üç <option> etiketi;
  • 11. satır: Seçilen kişi gerçekten de [Id]=2'dir.

Yukarıdaki iki örnek bize yeterli olacaktır. Bir [Razor] görünümü yazarken, içine mantık ekleme isteğine karşı koymak gerekir. C# kodu bunu bize izin verirdi. Ancak, MVC modelinde mantık, eylemde veya alt katmanlarda ([Metier, DAO]) bulunmalı, görünümde olmamalıdır. MVC modeline uyulsa bile, ara değerleri hesaplamak için görünümde çok fazla mantık bulunabilir. Bu, kullanılan modelin yeterince ayrıntılı olmadığı anlamına gelebilir. Model, görünümün bunları kendisi hesaplamak zorunda kalmaması için ihtiyaç duyduğu nihai değerleri içermelidir. İyi bir görünüm, mantık kodunun en aza indirgendiği ve görünümün HTML yapısının net kaldığı bir görünümdür. Çok fazla C# kodu eklenirse, HTML yapısı okunaksız hale gelebilir.

Yukarıdaki örnekte, açılır liste bir kullanıcı tarafından kullanılabilir ve bu durumda kullanıcının hangi kişiyi seçtiğini bilmek isteyebiliriz. Bunun için bir forma ihtiyacımız var.

5.5. Form – ilk adımlar

Kullanıcıya sunulan form şu şekilde olacaktır:

 

Görünüm şablonu, daha önce kullanılmış olan [ViewModel05] şablonu olacaktır. Bu görünümü görüntüleyecek eylem şu şekilde olacaktır:


    // Eylem06-GET
    [HttpGet]
    public ViewResult Action06()
    {
      return View("Action06Get",new ViewModel05());
}
  • 2. satır: Eylem yalnızca HTTP GET komutuyla çağrılabilir;
  • 5. satır: [/First/Action06Get.cshtml] görünümü, [ViewModel05] türünde bir örnek kullanılarak görüntülenecektir.

[/First/Action06Get.cshtml] görünümü şu şekilde olacaktır:


@model Exemple_03.Models.ViewModel05
@using Exemple_03.Models

@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action06-GET</title>
</head>
<body>
  <h3>Action06 - GET</h3>
  <p>Choisissez une personne</p>
  <form method="post" action="/First/Action06">
    <select name="personneId">
      @foreach (Personne2 p in Model.Personnes)
      {
        string selected = "";
        if (p.Id == Model.SelectedId)
        {
          selected = "selected=\"selected\"";
        }
        <option value="@p.Id" @selected>@p.Prénom @p.Nom</option>
      }
    </select>
    <input name="valider" type="submit" value="Valider" />
  </form>
</body>
</html>

Başlıca yenilikler şunlardır:

  • 18. satır: Tarayıcının kullanıcı tarafından girilen bilgileri iletebilmesi için bir forma ihtiyacımız vardır. Bu form, 18. ve 31. satırlardaki <form> etiketiyle sınırlandırılmıştır.

HTML <form> etiketi 2.5.2.1. paragrafında tanıtılmıştı. Özelliklerini hatırlayalım:

form

<form method="post" action="FormulairePost.aspx">
HTML etiketi
<form name="..." method="..." action="...">...</form>
öznitelikler
name="frmexemple": formun adı - isteğe bağlı
method="..." : tarayıcının, formda toplanan değerleri web sunucusuna göndermek için kullandığı yöntem
action="..." : Formda toplanan değerlerin gönderileceği adres.
Bir web formu, <form>...</form> etiketleriyle çevrelenir. Formun bir adı olabilir (name="xx"). Formda bulunan tüm denetimler için de durum böyledir. Bir formun amacı, kullanıcının klavye veya fare ile girdiği bilgileri toplamak ve bunları bir web sunucusunun URL adresine göndermektir. Hangi adrese? action="URL" özniteliğinde belirtilen adrese. Bu öznitelik yoksa, bilgiler formun bulunduğu belgenin URL adresine gönderilir. Bir web istemcisi, bir web sunucusuna veri göndermek için POST ve GET adlı iki farklı yöntem kullanabilir. method="méthode" özniteliği, method'in GET veya POST'e eşit olması durumunda, <form> etiketindeki bu öznitelik, tarayıcıya formda toplanan bilgileri action="URL" özniteliğiyle belirtilen URL adresine göndermek için kullanılacak yöntemi bildirir. method özniteliği belirtilmediğinde, varsayılan olarak GET yöntemi kullanılır.
  • 18. satır: Form değerlerinin bir HTTP POST komutu aracılığıyla URL [/First/Action06]'e gönderileceği görülmektedir;
  • 30. satır: Bir formda [submit] türünde bir düğme bulunmalıdır. Girilen değerlerin, <form> etiketinin [action] özniteliğiyle belirtilen URL'e gönderilmesini tetikleyen bu düğmedir.

Kullanıcı [Valider] düğmesine tıkladığında tarayıcı tam olarak neyi iletecek? Bu konu 2.5.3.1. paragrafında açıklanmıştır. Daha önce söylenenleri hatırlayalım:


HTML kontrolü


görsel


döndürülen değer(ler)

<input type="radio" value="Evet" name="R1"/>Evet
<input type="radio" name="R1" value="hayır" checked="checked"/>Hayır
R1=Evet
- kullanıcı tarafından işaretlenen radyo düğmesinin value özniteliğinin değeri.
<input type="checkbox" name="C1" value="bir"/>1
<input type="checkbox" name="C2" value="iki" checked="checked"/>2
<input type="checkbox" name="C3" value="üç"/>3
C1=bir
C2=iki
- kullanıcı tarafından işaretlenen kutuların value öznitelik değerleri
<input type="text" name="txtSaisie" size="20" value="birkaç kelime"/>
txtSaisie=Web+programlama
- kullanıcı tarafından giriş alanına yazılan metin. Boşluklar + işaretiyle değiştirilmiştir
<input type="password" name="txtMdp" size="20" value="unMotDePasse"/>
txtMdp=bu bir sır
- kullanıcı tarafından giriş alanına yazılan metin
<textarea rows="2" name="areaSaisie" cols="20">
satır1
satır2
satır3
</textarea>
giriş alanı=Web+programlamanın+temelleri%0D%0A
Web+programlama
- kullanıcı tarafından giriş alanına yazılan metin. %OD%OA satır sonu işaretidir. Boşluklar + işaretiyle değiştirilmiştir
<select size="1" name="cmbValeurs">
<option value='1'>seçim1</option>
<option selected="selected" value='2'>seçenek2</option>
<option value='3'>seçenek3</option>
</select>
cmbDeğerler=3
- kullanıcı tarafından seçilen öğenin [value] özniteliği
<select size="3" name="lst1">
<option selected="selected" value='1'>liste1</option>
<option value='2'>liste2</option>
<option value='3'>liste3</option>
<option value='4'>liste4</option>
<option value='5'>liste5</option>
</select>
lst1=3
- kullanıcı tarafından seçilen öğenin [value] özniteliği
<select size="3" name="lst2" multiple="multiple">
<option selected="selected" value='1'>liste1</option>
<option value='2'>liste2</option>
<option selected="selected" value='3'>liste3</option>
<option value='4'>liste4</option>
<option value='5'>liste5</option>
</select>
lst2=1
lst2=3
- kullanıcı tarafından seçilen öğelerin [value] öznitelikleri
<input type="submit" value="Gönder" name="cmdRenvoyer"/>
 
cmdRenvoyer=Gönder
- form verilerini sunucuya göndermek için kullanılan düğmenin adı ve value özniteliği
<input type="hidden" name="secret" value="uneValeur"/>
 
secret=birDeğer
- gizli alanın value özniteliği

Formumuzda, bir değer gönderebilecek iki etiket bulunmaktadır:


    <select name="personneId">
...
</select>

ve


<input name="valider" type="submit" value="Valider" />

Kullanıcı 2 numaralı kişiyi seçerse, gönderilen değerler şu şekilde olacaktır:

personneId=2&valider=Valider

Parametrelerin adları, POST ile ilgili etiketlerin [name] özniteliklerinin adlarıdır. Bu öznitelik olmadan etiketler herhangi bir değer göndermez. Dolayısıyla yukarıdaki örnekte, [submit] düğmesinin name="valider" özniteliği atlanabilir. Gönderilen değer, düğmenin [value] özniteliğidir. Burada bu bilgi bizim için önemli değildir. Bazen formlarda [submit] türünde birden fazla düğme bulunur. Bu durumda hangi düğmeye tıklandığını bilmek önemlidir. Bu durumda, farklı düğmelere [name] özniteliği eklenir.

<select> etiketi, bir dizi <option> etiketinden oluşur:


    <select name="personneId">
        <option value="1" >Pierre Martino</option>
        <option value="2" selected=&quot;selected&quot;>Pauline Pereiro</option>
        <option value="3" >Jacques Alfonso</option>
</select>

Gönderilen, seçilen seçeneğin [value] özniteliğinin değeridir. Bu özniteliğin bulunmaması durumunda, seçeneğin görüntülediği metin, örneğin [Pierre Martino], gönderilir.

Şu dize

personneId=2&valider=Valider

şu şekilde gönderilecektir: URL [/First/Action06]:


    // Eylem06-POST
    [HttpPost]
    public ViewResult Action06(ActionModel06 modèle)
    {
      return View("Action06Post",modèle);
}

Belki hatırlarsınız, daha önce [Action06] adlı bir eylemimiz vardı:


    // Eylem06-GET
    [HttpGet]
    public ViewResult Action06()
    {
      return View("Action06Get",new ViewModel05());
}

Aynı komutları işlememesi koşuluyla, aynı ada sahip iki eylem bulunabilir: HTTP:

  • 3. satırdaki [Action06], 2. satırdaki POST'i yönetir;
  • c satırındaki [Action06], GET'i (b satırı) yönetir.

POST'i yöneten [Action06] eylemi, aşağıdaki parametre dizisini alacaktır:

personneId=2&valider=Valider

Bu değerleri kapsüllemek için bir eylem şablonuna ihtiyacımız var. Bu, aşağıdaki [ActionModel06] şablonu olacaktır:


using System.ComponentModel.DataAnnotations;
namespace Exemple_03.Models
{
  public class ActionModel06
  {
    [Required(ErrorMessage = "Le paramètre [personneId] est requis")]
    public int PersonneId { get; set; }

    [Required(ErrorMessage = "Le paramètre [valider] est requis")]
    public string Valider { get; set; }
  }
}

[Action06] eylemi bu şablonu alır ve olduğu gibi aşağıdaki [Action06Post] görünümüne (eylemin 5. satırı) iletir:


@model Exemple_03.Models.ActionModel06

@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action06Post</title>
</head>
<body>
  <h3>Action06 - POST</h3>
  Valeurs postées :
  <ul>
    <li>ID de la personne sélectionnée : @Model.PersonneId</li>
    <li>Commande utilisée : @Model.Valider</li>
  </ul>
</body>
</html>

Şablon, 18. ve 19. satırlarda görüntülenir.

Bir örneğe bakalım:

[1]'te, [Id]'teki üçüncü kişi (değeri 3 olan) seçilir. [2]'te form gönderilir. [3]'te alınan değerler gösterilir. [4,5]'te, aynı URL'in bir tanesinin GET ve [4] tarafından, diğeri ise bir POST ve [5] tarafından çağrılmıştır. Bu durum URL'te görülmemektedir.

POST'in ardından görüntülenen görünümde, seçilen kişinin numarası yerine nom ve prénom'leri görmek isteyebilirsiniz. Bu durumda, POST görünümünü ve şablonunu güncellemek gerekir.

Bu durumu ele almak için [Action07] adlı bir eylem oluşturuyoruz. Bu eylem, kişi listesini depolamak için kullanıcının oturumunu kullanmak zorunda olacaktır. 4.10 numaralı paragrafta incelenen modeli takip edeceğiz; bu model, [Application] ve [Session] kapsamındaki verilerin eylem modeline dahil edilmesini sağlar.

Oturum modeli, aşağıdaki [SessionModel] sınıfı olacaktır:


namespace Exemple_03.Models
{
  public class SessionModel
  {
    public Personne2[] Personnes { get; set; }
  }
}
  • 2. satır: Oturum, açılır listede görüntülenen kişilerin listesini saklayacaktır;

Önceki [SessionModel] türünü, [SessionModelBinder] adını vereceğimiz bir bağlayıcıya bağlamamız gerekiyor. Bu, sayfa 82'de açıklananla aynı olacaktır:

  

using System.Web.Mvc;

namespace Exemple_03.Infrastructure
{
  public class SessionModelBinder : IModelBinder
  {
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
      // [Session] kapsamındaki verileri geri gönderir
      return controllerContext.HttpContext.Session["data"];
    }
  }
}

[SessionModel] şablonu ile binder ve [SessionModelBinder] şablonları arasındaki bağlantı, [Global.asax] içinde yapılır:


public class MvcApplication : System.Web.HttpApplication
  {
    protected void Application_Start()
    {
      ...

      // model bağlayıcıları
      ModelBinders.Binders.Add(typeof(SessionModel), new SessionModelBinder());
    }
    // Oturum
    public void Session_Start()
    {
      Session["data"] = new SessionModel();
    }
  }
  • 8. satır: modelin bağlayıcısına bağlanması [Application_Start] dosyasında gerçekleştirilir;
  • 13. satır: [SessionModel] türünde bir örnek, [data] anahtarıyla ilişkilendirilerek oturuma eklenir.

Bu işlem tamamlandıktan sonra, [Action07] eylemi şu şekildedir:


    // Eylem07-GET
    [HttpGet]
    public ViewResult Action07(SessionModel session)
    {
      ViewModel05 modèleVue = new ViewModel05();
      session.Personnes= modèleVue.Personnes;
      return View("Action07Get", modèleVue);
}
  • 3. satır: eylem, [SessionModel] türünü alır; dolayısıyla, [data] anahtarına bağlı [Session] kapsam verisini alır;
  • 5. satır: Görünüm şablonu oluşturulur;
  • 6. satır: Kişiler dizisi oturuma eklenir. Buna bir sonraki sorguda, yani POST sorgusunda ihtiyaç duyulacaktır. HTTP protokolü durum bilgisi içermeyen bir protokoldür. İstekler arasında bellek ayırmak için bir oturum kullanılması gerekir. Bir oturum, kullanıcıya özeldir ve web sunucusu tarafından yönetilir;
  • 7. satır: [Action07Get.cshtml] görünümü görüntülenir. Bu görünüm şöyledir:

@model Exemple_03.Models.ViewModel05
@using Exemple_03.Models
...
<body>
  <h3>Action07 - GET</h3>
  <p>Choisissez une personne</p>
  <form method="post" action="/First/Action07">
....
  </form>
</body>
</html>

Bu, daha önce incelediğimiz [Action06Get.cshtml] görünümüyle aynıdır. Temel fark 7. satırda görülür: form değerlerinin gönderileceği URL. Bu değerler, aşağıdaki [Action07] eylemi tarafından işlenecektir:


    // Eylem07-POST
    [HttpPost]
    public ViewResult Action07(SessionModel session, ActionModel06 modèle)
    {
      Personne2 personne = session.Personnes.Where(p => p.Id == modèle.PersonneId).First<Personne2>();
      string strPersonne = string.Format("{0} {1}", personne.Prénom, personne.Nom);
      return View("Action07Post", (object)strPersonne);
}
  • 3. satır: Gönderilen değerler, daha önce (aşağıda) kullanılmış olan [ActionModel06] eylem şablonuna yerleştirilir:

using System.ComponentModel.DataAnnotations;
namespace Exemple_03.Models
{
  public class ActionModel06
  {
    [Required(ErrorMessage = "Le paramètre [personneId] est requis")]
    public int PersonneId { get; set; }

    [Required(ErrorMessage = "Le paramètre [valider] est requis")]
    public string Valider { get; set; }
  }
}
  • 3. satır: ilk parametre, [data] anahtarıyla ilişkili [Session] kapsam verisidir;
  • satır 5: LINQ sorgusu, gönderilen [Id]'e sahip kişiyi alır;
  • 6. satır: [Action07Post] görünümü (8. satır) tarafından görüntülenmesi gereken karakter dizisi oluşturulur;
  • 7. satır: Doğru [View] oluşturucusunu çağırmak için, [string] türünü [object] olarak yeniden tanımlamak gerekir.

[Action07Post.cshtml] görünümü şu şekildedir:


@model string

@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action07-Post</title>
</head>
<body>
  <h3>Action07-POST</h3>
  Vous avez sélectionné [@Model].
</body>
</html>
  • 1. satır: şablonun türü [string]'tir;
  • 16. satır: karakter dizisi görüntülenir.

İşte bir yürütme örneği:

5.6. Form – tam bir örnek

2.5.2.1 numaralı paragrafta, aşağıdaki HTML formunu incelemiştik:

1
 

Bu formu görüntüleyen (GET) [Action08Get] eylemini ve kullanıcı tarafından girilen değerleri işleyen (POST) [Action08Post] eylemini inceleyeceğiz. Klasik bir şema.

Yukarıdaki [1] görünüm şablonu, [ViewModel08] sınıfının bir örneği olacaktır. Bu sınıf, aynı zamanda:

  • [Action08Get] eylemi üzerinde GET tarafından üretilen görünümün modeli;
  • POST isteği için [Action08Post] eyleminin modeli olacaktır.

5.6.1. [Application] kapsam şablonu

Radyo düğmeleri, onay kutuları ve çeşitli listeler tarafından görüntülenen öğelerin [Application] kapsamındaki veriler olduğunu varsayacağız. Bu sık karşılaşılan bir durumdur. Bu bilgiler, uygulamanın başlatılması sırasında [Global.asax] sınıfındaki [Application_Start] yönteminde işlenen bir yapılandırma dosyasından veya veritabanından alınır. Bu yöntem şu şekilde ilerler:


    protected void Application_Start()
    {
....

      // model bağlayıcıları
      ModelBinders.Binders.Add(typeof(SessionModel), new SessionModelBinder());
      ModelBinders.Binders.Add(typeof(ApplicationModel), new ApplicationModelBinder());

      // kapsam verileri [Application]
      Application["data"] = new ApplicationModel();
}
  • 7. satır: Kısa süre sonra açıklayacağımız [ApplicationModel] türü, daha önce 82. sayfada tanıttığımız [ApplicationModelBinder] veri bağlayıcısıyla ilişkilendirilir;
  • 10. satır: [ApplicationModel] türünde bir örnek, [data] anahtarıyla ilişkilendirilerek uygulama sözlüğüne kaydedilir.

[ApplicationModel] sınıfı, [Application] kapsamındaki tüm verileri kapsüllemek için kullanılır. Burada, formun görüntülemesi gereken verileri kapsülleyecektir:


namespace Exemple_03.Models
{
  public class ApplicationModel
  {
    // formda görüntülenecek koleksiyonlar
    public Item[] RadioButtonFieldItems { get; set; }
    public Item[] CheckBoxesFieldItems { get; set; }
    public Item[] DropDownListFieldItems { get; set; }
    public Item[] SimpleChoiceListFieldItems { get; set; }
    public Item[] MultipleChoiceListFieldItems { get; set; }

    // alanların ve koleksiyonların başlatılması
    public ApplicationModel()
    {
      RadioButtonFieldItems = new Item[]{
        new Item {Value="1",Label="oui"},
        new Item {Value="2", Label="non"}
      };
      CheckBoxesFieldItems = new Item[]{
        new Item {Value="1",Label="1"},
        new Item {Value="2", Label="2"},
        new Item {Value="3", Label="3"}
      };
      DropDownListFieldItems = new Item[]{
        new Item {Value="1",Label="choix1"},
        new Item {Value="2", Label="choix2"},
        new Item {Value="3", Label="choix3"}
      };
      SimpleChoiceListFieldItems = new Item[]{
        new Item {Value="1",Label="liste1"},
        new Item {Value="2", Label="liste2"},
        new Item {Value="3", Label="liste3"},
        new Item {Value="4", Label="liste4"},
        new Item {Value="5", Label="liste5"}
      };
      MultipleChoiceListFieldItems = new Item[]{
        new Item {Value="1",Label="liste1"},
        new Item {Value="2", Label="liste2"},
        new Item {Value="3", Label="liste3"},
        new Item {Value="4", Label="liste4"},
        new Item {Value="5", Label="liste5"}
      };
    }
    // koleksiyon öğesi
    public class Item
    {
      public string Label { get; set; }
      public string Value { get; set; }
    }

  }
}
  • 45-49. satırlar: formun çeşitli koleksiyonlarına ait öğeler. [Label], form öğesi tarafından görüntülenen metindir; [Value] ise bu öğe seçildiğinde gönderilen değerdir;
  • 6. satır: Radyo düğmesi tarafından görüntülenen koleksiyon;
  • 7. satır: onay kutuları tarafından görüntülenen koleksiyon;
  • satır 8: açılır liste tarafından görüntülenen koleksiyon;
  • 9. satır: Tek seçim listesi tarafından görüntülenen koleksiyon;
  • satır 10: çoklu seçim listesi tarafından görüntülenen koleksiyon;
  • satır 13-43: Bu koleksiyonlar, sınıfın parametresiz oluşturucusu tarafından başlatılır.

Farklı koleksiyonlar aşağıdaki formu dolduracaktır:

5.6.2. [Action08Get] eyleminin şablonu

Yukarıdaki form, aşağıdaki [Action08Get] eylemi tarafından görüntülenecektir:


    // Action08-GET
    [HttpGet]
    public ViewResult Action08Get(ApplicationModel application)
    {
      ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
      return View("Formulaire", new ViewModel08(application));
}
  • 2. satır: [Action08Get], yalnızca [GET] komutuna yanıt verecektir;
  • 3. satır: Bu komut, az önce tanımladığımız uygulama şablonunu parametre olarak alır;
  • 5. satır: [ViewBag] dinamik konteynerinde bir bilgiyi başlatır;
  • 6. satır: [/First/Formulaire.cshtml] görünümünü, [ViewModel08] modeli ile görüntüler. Bu model, daha önce sunulan formun modelidir. Bunun için, görüntülenecek öğeleri tanımlayan uygulama modelini oluşturucuya aktarırız.

5.6.3. [Formulaire] görünümünün şablonu

[ViewModel08] sınıfı, formun şablonu olacaktır. Bu sınıf şu şekildedir:


using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using Exemple_03.Models;

namespace Exemple_03.Models
{
  public class ViewModel08
  {
    // giriş alanları
    public string RadioButtonField { get; set; }
    public string[] CheckBoxesField { get; set; }
    public string TextField { get; set; }
    public string PasswordField { get; set; }
    public string TextAreaField { get; set; }
    public string DropDownListField { get; set; }
    public string SimpleChoiceListField { get; set; }
    public string[] MultipleChoiceListField { get; set; }

    // formda görüntülenecek koleksiyonlar
    public ApplicationModel.Item[] RadioButtonFieldItems { get; set; }
    public ApplicationModel.Item[] CheckBoxesFieldItems { get; set; }
    public ApplicationModel.Item[] DropDownListFieldItems { get; set; }
    public ApplicationModel.Item[] SimpleChoiceListFieldItems { get; set; }
    public ApplicationModel.Item[] MultipleChoiceListFieldItems { get; set; }

    // oluşturucular
    public ViewModel08()
    {
    }

    public ViewModel08(ApplicationModel application)
    {
      // koleksiyonların başlatılması
      RadioButtonFieldItems = application.RadioButtonFieldItems;
      CheckBoxesFieldItems = application.CheckBoxesFieldItems;
      DropDownListFieldItems = application.DropDownListFieldItems;
      SimpleChoiceListFieldItems = application.SimpleChoiceListFieldItems;
      MultipleChoiceListFieldItems = application.MultipleChoiceListFieldItems;
      // alanların başlatılması
      RadioButtonField = "2";
      CheckBoxesField = new string[] { "2" };
      TextField = "quelques mots";
      PasswordField = "secret";
      TextAreaField = "ligne1\nligne2";
      DropDownListField = "2";
      SimpleChoiceListField = "3";
      MultipleChoiceListField = new string[] { "1", "3" };
    }
  }
}
  • Bir formda iki tür öğe bulunur: görüntülenenler ve giriş yapılanlar;
  • 20-24. satırlar, görüntülenecek öğeleri tanımlar. Bunlar, formun çeşitli koleksiyonlarıdır. Bunlar, uygulama şablonunda (34-38. satırlar) bulunur;
  • 10-17. satırlar: formun giriş alanlarını tanımlar;
  • 10. satır: [RadioButtonField], formun sonraki satırları tarafından gönderilen değeri alacaktır:

        <!-- radyo düğmeleri -->
        <tr>
          <td>Etes-vous marié(e)</td>
          <td>
<input type="radio" name="RadioButtonField" value="1" />oui              
<input type="radio" name="RadioButtonField" value="2" checked=&quot;checked&quot;/>non              
          </td>
</tr>

5. ve 6. satırlarda, iki radyo düğmesinin [name] özniteliğinin, başlatılacak olan özelliğin adı olduğuna dikkat edilmelidir. Gönderilen verilerde şu biçimde bir dize bulunur:


param1=val1&RadioButtonField=2&param2=val2

Kullanıcı, [non] adlı seçeneği işaretlediyse. Aslında, işaretlenen seçeneğin [value] özniteliği gönderilir.

  • 11. satır: [CheckBoxesField], formun sonraki satırlarında gönderilen değerleri alacaktır:

        <!-- onay kutuları -->
        <tr>
          <td>Cases à cocher</td>
          <td>
<input type="checkbox" name="CheckBoxesField" value="1" />1              
<input type="checkbox" name="CheckBoxesField" value="2" checked=&quot;checked&quot;/>2              
<input type="checkbox" name="CheckBoxesField" value="3" />3              
</td>

5. ve 6. satırlarda, onay kutularının [name] özniteliğinin, başlatılacak özelliğin adı olduğuna dikkat edilmelidir. Gönderilen verilerde şu biçimde bir dize bulunur:


param1=val1&CheckBoxesField=2&CheckBoxesField=3&param2=val2

Kullanıcı, [2] ve [3] etiketli onay kutularını işaretlediyse. İşlem sırasında gönderilen, işaretlenen seçeneklerin [value] özniteliğidir. Aynı isimde birden fazla parametre gönderilebildiğinden, [CheckBoxesField] tek bir değer değil, bir değerler dizisidir. Hiçbir kutucuk işaretlenmemişse, [CheckBoxesField] parametresi gönderilen dizede yer almayacak ve şablondaki aynı isimli özellik başlatılmayacaktır. Görüleceği üzere bu durum sorun yaratabilir.

  • 12. satır: [TextField], formun sonraki satırları tarafından gönderilen değeri alacaktır:

          <!-- tek satırlık metin giriş alanı -->
          <tr>
            <td>Champ de saisie</td>
            <td>
              <input type="text" name="TextField" value="quelques mots" size="30" />
            </td>
</tr>

5. satırda, giriş alanının [name] özniteliği, başlatılacak özelliğin adıdır. Gönderilen verilerde şu biçimde bir dize bulunur:


param1=val1&TextField=abcdef&param2=val2

kullanıcı giriş alanına [abcdef] değerini girmişse.

  • 13. satır: [PasswordField], formun sonraki satırlarında gönderilen değeri alacaktır:

        <!-- şifre giriş alanı -->
        <tr>
          <td>Mot de passe</td>
          <td>
            <input type="password" name="PasswordField" value="secret" size="30" />
          </td>
</tr>

5. satırda, giriş alanının [name] özniteliği, başlatılacak özelliğin adıdır. Gönderilen verilerde şu biçimde bir dize bulunur:


param1=val1&PasswordField=abcdef&param2=val2

Kullanıcı giriş alanına [abcdef] değerini girmişse.

  • 14. satır: [TextAreaField], formun sonraki satırlarında gönderilen değeri alacaktır:

        <!-- çok satırlı metin giriş alanı -->
        <tr>
          <td>Boîte de saisie</td>
          <td>
            <textarea name="TextAreaField" cols="40" rows="3">ligne1
ligne2</textarea>
          </td>
</tr>

5. satırda, giriş alanının [name] özniteliği, başlatılacak özelliğin adıdır. Gönderilen verilerde şu biçimde bir dize bulunur:


param1=val1&TextAreaField=abcdef%0D%OAhijk&param2=val2

Kullanıcı, giriş alanına [abcdef] yazıp bir satır atladıktan sonra [ijk] yazmışsa.

  • 15. satır: [DropDownListField], formun sonraki satırlarında gönderilen değeri alacaktır:

        <!-- açılır liste -->
        <tr>
          <td>Liste déroulante</td>
          <td>
            <select name="DropDownListField">
<option value="1" >choix1</option>
<option value="2" selected=&quot;selected&quot;>choix2</option>
<option value="3" >choix3</option>
            </select>
</tr>

5. satırda, <select> etiketinin [name] özniteliği, başlatılacak özelliğin adıdır. Gönderilen verilerde şu biçimde bir dize bulunur:


param1=val1&DropDownListField=1&param2=val2

Kullanıcı [choix1] seçeneğini seçtiyse, gönderilen değer seçilen seçeneğin [value] özniteliğidir.

  • 16. satır: [SingleChoiceListField], formun sonraki satırları tarafından gönderilen değeri alacaktır:

        <!-- tek seçimli liste -->
        <tr>
          <td>Liste à choix unique</td>
          <td>
            <select name="SimpleChoiceListField" size="3">
<option value="1" >liste1</option>
<option value="2" >liste2</option>
<option value="3" selected=&quot;selected&quot;>liste3</option>
<option value="4" >liste4</option>
<option value="5" >liste5</option>

            </select>
</tr>

5. satırda, <select> etiketinin [name] özniteliği, başlatılacak özelliğin adıdır. Açılır menü olmaması, [size="3"] özniteliği sayesinde sağlanır. Gönderilen verilerde şu biçimde bir dize bulunur:


param1=val1&SimpleChoiceListField=3&param2=val2

Kullanıcı [liste3] seçeneğini seçtiyse, gönderilen veri, seçilen seçeneğin [value] özniteliğidir. Hiçbir öğe seçilmediyse, gönderilen dizede [SingleChoiceListField] parametresi bulunmayabilir.

  • 17. satır: [MultipleChoiceListField], formun aşağıdaki satırlarından gönderilen değerleri alacaktır:

        <!-- çoktan seçmeli liste -->
        <tr>
          <td>Liste à choix multiple</td>
          <td>
            <select name="MultipleChoiceListField" size="3" multiple="multiple">
<option value="1" selected=&quot;selected&quot;>liste1</option>
<option value="2" >liste2</option>
<option value="3" selected=&quot;selected&quot;>liste3</option>
<option value="4" >liste4</option>
<option value="5" >liste5</option>
            </select>
</tr>

5. satırda, <select> etiketinin [name] özniteliği, başlatılacak özelliğin adıdır. Açılır menü olmaması [size="3"] özniteliği sayesinde sağlanır; kullanıcının [Ctrl] tuşunu basılı tutarak birden fazla öğe seçebilmesi ise [multiple] özniteliği sayesinde sağlanır. Gönderilen verilerde şu biçimde bir dize bulunur:


param1=val1&MultipleChoiceListField=1&MultipleChoiceListField=3&param2=val2

Kullanıcı [liste1] ve [liste3] seçeneklerini seçtiyse. Gönderilen, seçilen seçeneklerin [value] özniteliğidir. Aynı isimde birden fazla parametre gönderilebildiğinden, [MultipleChoiceListField] tek bir değer değil, bir değer dizisidir. Hiçbir kutucuk işaretlenmemişse, [MultipleChoiceListField] parametresi gönderilen dizede yer almayacak ve modeldeki aynı isimli özellik başlatılmayacaktır.

Yukarıda gösterilen çeşitli giriş alanları, form tarafından gönderilen değerleri alacaktır. Formu göndermeden önce bu alanları da önceden başlatabilirsiniz. Burada yapılan da budur:


      // alanların başlatılması
      RadioButtonField = "2";
      CheckBoxesField = new string[] { "2" };
      TextField = "quelques mots";
      PasswordField = "secret";
      TextAreaField = "ligne1\nligne2";
      DropDownListField = "2";
      SimpleChoiceListField = "3";
MultipleChoiceListField = new string[] { "1", "3" };

Bu değerler, formun POST seçeneği seçildikten sonra elde edilmiş olsaydı, bu durum kullanıcının şunları yaptığı anlamına gelirdi:

  • 2. satır: radyo düğmesindeki [non] seçeneğini işaretlemiş;
  • 3. satır: onay kutularından [2] seçeneğini işaretlemiş;
  • 4. satır: giriş alanına [quelques mots] yazmış;
  • 5. satır: [secret] şifresini girmiştir;
  • 6. satır: çok satırlı giriş alanına [ligne1\nligne2] yazın;
  • 7. satır: açılır listeden [choix2] seçeneğini seçin;
  • satır 8: tek seçimli listeden [liste3] seçeneğini seçin;
  • 9. satır: çoklu seçim listesinden [liste1] ve [liste3] seçeneklerini seçin;

POST işleminin gerçekleştiğini ve formun girildiği haliyle geri gönderilmesini istediğimizi varsayalım. Bu, özellikle hatalı bir formun kullanıcıya geri gönderilmesi durumunda yapılan işlemdir. Form, girildiği haliyle geri gönderilir.

5.6.4. [Formulaire] görünümü

[/First/Formulaire.cshtml] görünümü, formu şu şekilde görüntüler:


@model Exemple_03.Models.ViewModel08
@using Exemple_03.Models
@{
  Layout = null;
}
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Formulaire</title>
</head>
<body>
  <form method="post" action="Action08Post">
    <h2>Formulaire ASP.NET MVC</h2>
    <h3>Affiché par : @ViewBag.info</h3>
    <table>
      <thead></thead>
      <tbody>
        <!-- radyo düğmeleri -->
        <tr>
          <td>Etes-vous marié(e)</td>
          <td>
            @foreach (ApplicationModel.Item item in @Model.RadioButtonFieldItems)
            {
              string strChecked = item.Value == @Model.RadioButtonField ? "checked=\"checked\"" : "";
              <input type="radio" name="RadioButtonField" value="@item.Value" @strChecked/>@item.Label
              <text/>
            }
          </td>
        </tr>
...
      </tbody>
    </table>
    <input type="submit" value="Valider" />
  </form>
</body>
</html>
  • 1. satır: [ViewModel08], form şablonudur;
  • 12. satır: Formun <form> etiketi. Bu form, [POST] yöntemi (method özniteliği) ile URL [/First/Action08Post] (action özniteliği) ile gönderilecektir;
  • 33. satır: Formu göndermek için kullanılan [submit] türündeki düğme;
  • 22-27. satırlar: radyo düğmelerini görüntüler:
  
  • 22. satır: radyo düğmesi tarafından görüntülenen koleksiyon arasında gezinilir;
  • satır 24: [value] özniteliğine sahip düğme, [RadioButtonField] özelliğinin değerini içermeli ve işaretlenmiş olmalıdır. Bunun için [checked="checked"] özniteliğine sahip olması gerekir;
  • satır 25: değeri [@item.Value] ve etiketi [@item.Label] olan <input type="radio"> etiketinin oluşturulması;
  • 26. satır: <text/> etiketi, tanınan bir HTML etiketi değildir. Bu etiket, [Razor] için yer almaktadır. Bu etikete rastlandığında, [Razor] bir satır sonu oluşturacaktır. Bu, görüntülenen form üzerinde bir etki yaratmaz ancak oluşturulan HTML kodunda bir etki yaratır. Böylece <input type="radio"> etiketleri aynı satırda olmak yerine iki farklı satıra yayılır. Bu, tarayıcıdan görüntülenen sayfanın kaynak kodunu görüntülemek istendiğinde kodu daha okunabilir hale getirir;

Görünümün diğer öğelerini de gözden geçiriyoruz:


        <!-- onay kutuları -->
        <tr>
          <td>Cases à cocher</td>
          <td>
            @{
              foreach (ApplicationModel.Item item in @Model.CheckBoxesFieldItems)
              {
                string strChecked = @Model.CheckBoxesField.Contains(item.Value) ? "checked=\"checked\"" : "";
              <input type="checkbox" name="CheckBoxesField" value="@item.Value" @strChecked/>@item.Label
              <text/>
              }
            }
</td>
  • 6. satır: onay kutuları tarafından görüntülenen koleksiyonu tarıyoruz;
  • 8. satır: [value] özniteliğine sahip bir kutucukta, [CheckBoxesField] özelliğinin değerlerinden biri işaretlenmiş olmalıdır. Bunun için, söz konusu kutucuğun [checked="checked"] özniteliğine sahip olması gerekir. Bir değerin bir tabloda yer alıp almadığını belirlemeye yarayan LINQ ifadesi kullanılır;
  • 25. satır: [@item.Value] değerine ve [@item.Label] etiketine sahip <input type="checkbox"> etiketinin oluşturulması;

<!-- tek satırlık metin giriş alanı -->
          <tr>
            <td>Champ de saisie</td>
            <td>
              <input type="text" name="TextField" value="@Model.TextField" size="30" />
            </td>
          </tr>
        <!-- şifre giriş alanı -->
        <tr>
          <td>Mot de passe</td>
          <td>
            <input type="password" name="PasswordField" value="@Model.PasswordField" size="30" />
          </td>
        </tr>
        <!-- çok satırlı metin giriş alanı -->
        <tr>
          <td>Boîte de saisie</td>
          <td>
            <textarea name="TextAreaField" cols="40" rows="3">@Model.TextAreaField</textarea>
          </td>
        </tr>
  • 5. ve 12. satırlar: etiketin [value] özniteliğine şablonun değeri atanır;
  • 19. satır: aynı işlem, ancak farklı bir sözdizimi ile.

        <!-- açılır liste -->
        <tr>
          <td>Liste déroulante</td>
          <td>
            <select name="DropDownListField">
              @{
                foreach (ApplicationModel.Item item in @Model.DropDownListFieldItems)
                {
                  string strChecked = item.Value == @Model.DropDownListField ? "selected=\"selected\"" : "";
                <option value="@item.Value" @strChecked>@item.Label</option>
                }
              }
            </select>
</tr>
  • 7. satır: açılır listede görüntülenen koleksiyon taranır;
  • 9. satır: [value] özniteliği, [DropDownListField] özelliğinin değerine sahip olan bir seçenek seçilmelidir. Bunun için, söz konusu seçeneğin [selected="selected"] özniteliğine sahip olması gerekir;
  • 25. satır: <option value="valeur">libellé</option> etiketinin, [@item.Value] değeriyle ve [@item.Label] etiket adıyla oluşturulması;

        <!-- tek seçimli liste -->
        <tr>
          <td>Liste à choix unique</td>
          <td>
            <select name="SimpleChoiceListField" size="3">
              @{
                foreach (ApplicationModel.Item item in @Model.SimpleChoiceListFieldItems)
                {
                  string strChecked = item.Value == @Model.SimpleChoiceListField ? "selected=\"selected\"" : "";
                <option value="@item.Value" @strChecked>@item.Label</option>
                }
              }
            </select>
</tr>

Açıklama, açılır listeyle aynıdır.


        <!-- çoklu seçim listesi -->
        <tr>
          <td>Liste à choix multiple</td>
          <td>
            <select name="MultipleChoiceListField" size="3" multiple="multiple">
              @{
                foreach (ApplicationModel.Item item in @Model.MultipleChoiceListFieldItems)
                {
                  string strChecked = @Model.MultipleChoiceListField.Contains(item.Value) ? "selected=\"selected\"" : "";
                <option value="@item.Value" @strChecked>@item.Label</option>
                }
              }
            </select>
</tr>
  • 7. satır: liste tarafından görüntülenen koleksiyon taranır;
  • 9. satır: [value] özniteliği, [MultipleChoiceListField] özelliğinin değerlerinden birini içeren bir seçenek seçilmelidir. Bunun için, seçeneğin [selected="selected"] özniteliğine sahip olması gerekir. Bir değerin bir dizide yer alıp almadığını belirlemeye yarayan LINQ ifadesi kullanılır;
  • 10. satır: <option value="valeur">libellé</option> etiketinin, [@item.Value] değeriyle ve [@item.Label] etiket adıyla oluşturulması;

5.6.5. Formdaki POST'in işlenmesi

Formun [Action08Post] eylemine gönderileceğini gördük:


  <form method="post" action="Action08Post">

[Action08Post] eylemi şu şekildedir:


    // Eylem08-POST
    [HttpPost]
    public ViewResult Action08Post(ApplicationModel application, FormCollection posted)
    {
      ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
      ViewModel08 modèle = new ViewModel08(application);
      TryUpdateModel(modèle,posted);
      return View("Formulaire", modèle);
}
  • 3. satır: Uygulama şablonu ve gönderilen değerler parametre olarak belirtilmiştir. Bu değerler [FormCollection] türünde mevcuttur. Gönderilen [RadioButtonField] parametresinin değeri, posted[" RadioButtonField"] ifadesi ile elde edilir. Burada bir karakter dizisi veya null işaretçisi elde edilir. posted[" CheckBoxesField"] yazılırsa, bir karakter dizisi dizisi veya null işaretçisi elde edilir;
  • neden şunu yazmayalım:

public ViewResult Action08Post(ApplicationModel application, ViewModel08 posted)

Bunun iki nedeni vardır:

  • birincisi, çerçeve [ViewModel08] modelini parametresiz oluşturucu ile örneklendirecektir; bu da modelin koleksiyonlarının başlatılmamasına neden olur;
  • ikincisi ise modele neyin gireceğini kontrol etmek istiyoruz. Model için dört olası kaynak olduğunu biliyoruz: bir GET'in parametreleri, bir POST'in parametreleri, kullanılan yol ve bir uploadé dosyasının parametreleri. Burada, modeli yalnızca gönderilen değerlerle başlatmak istiyoruz.
  • 6. satır: Modeli doğru oluşturucu kullanılarak başlatıyoruz;
  • 7. satır: Modeli gönderilen değerlerle başlatıyoruz. Bu işlemden sonra model, kullanıcı tarafından girilen verilere karşılık gelir;
  • 8. satır: Formu yeniden görüntülüyoruz. Kullanıcı, formu girdiği haliyle görecektir.

Bir örneğe bakalım:

[2]'te, [POST]'in sonucu, [1]'te girilenleri doğru bir şekilde yansıtmaktadır.

5.6.6. POST'teki Anormalliklerin İşlenmesi

Daha önce, [CheckBoxesField, SimpleChoiceListField, MultipleChoiceListField] alanları için hiçbir değer işaretlenmemiş veya seçilmemişse, ilgili parametrelerin gönderilen dizgiye dahil edilmediğini ve dolayısıyla şablondaki aynı adlı özelliklerin başlatılmadığını belirtmiştik.

Şu örneği inceleyelim:

  • [1]'te hiçbir onay kutusu işaretlenmemiştir;
  • [2]'te ise, [POST] bir onay kutusunu işaretli olarak geri getiriyor.

Bunun açıklaması şöyledir:

  • hiçbir kutucuk işaretlenmediği için, [CheckBoxesField] parametresi gönderilen değerler arasında yer almıyor;
  • [Action08Post] eylemi şu şekilde ilerler:

    [HttpPost]
    public ViewResult Action08Post(ApplicationModel application, FormCollection posted)
    {
      ViewBag.info = ...
      ViewModel08 modèle = new ViewModel08(application);
      TryUpdateModel(modèle,posted);
      return View("Formulaire", modèle);
}
  • 5. satır: Form şablonu oluşturulur. Ancak kullanılan oluşturucu, ["2"] dizisini [CheckBoxesField] özelliğine atar;
  • 6. satır: gönderilen değerler şablona kaydedilir. [CheckBoxesField] parametresi gönderilen değerler arasında yer almadığından, aynı adlı özellik atanmaz. Dolayısıyla bu özellik ["2"] değerini korur; bu da ekranda 2 numaralı kutucuğun işaretli görünmesine neden olur, oysa işaretli olmaması gerekir.

Bu sorun çeşitli şekillerde çözülebilir. Biz, sorunu [Action08Post] eyleminin kodunda çözmeyi tercih ediyoruz:


// Eylem08-POST
    [HttpPost]
    public ViewResult Action08Post(ApplicationModel application, FormCollection posted)
    {
      ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
      ViewModel08 modèle = new ViewModel08(application);
      TryUpdateModel(modèle,posted);
      // gönderilmemiş değerlerin işlenmesi
      if (posted["CheckBoxesField"] == null)
      {
        modèle.CheckBoxesField = new string[] { };
      }
      if (posted["SimpleChoiceListField"] == null)
      {
        modèle.SimpleChoiceListField = "";
      }
      if (posted["MultipleChoiceListField"] == null)
      {
        modèle.MultipleChoiceListField = new string[] { };
      }
      // form görüntüleme
      return View("Formulaire", modèle);
    }
  • 9-20. satırlar: Bazı parametrelerin gönderilip gönderilmediğini kontrol ediyoruz. Gönderilmemişlerse, kullanıcı tarafından giriş yapılmamış olması durumuna karşılık gelen değerle başlatıyoruz. Açılır liste için bu kontrol yapılmamıştır; bu listede her zaman bir öğe seçili durumdadır, ancak diğer listelerde durum böyle değildir.

Okuyucuların bu yeni sürümü test etmeleri önerilir.

5.7. Form oluşturmada özel yöntemlerin kullanımı

5.7.1. Yeni form

Öncekiyle aynı bir form üretecek olan [Formulaire2.cshtml] adlı yeni bir form oluşturuyoruz:

Formdaki açılır listeyi oluşturmak için kullanılan koda tekrar bir göz atalım:


        <!-- açılır liste -->
        <tr>
          <td>Liste déroulante</td>
          <td>
            <select name="DropDownListField">
              @{
                foreach (ApplicationModel.Item item in @Model.DropDownListFieldItems)
                {
                  string strChecked = item.Value == @Model.DropDownListField ? "selected=\"selected\"" : "";
                <option value="@item.Value" @strChecked>@item.Label</option>
                }
              }
            </select>
</tr>

Bu kodun iki dezavantajı vardır:

  • en önemlisi, kodun karmaşıklığı nedeniyle bileşenin niteliğini (burada bir açılır liste) gözden kaçırmamızdır;
  • 5. satır: [name] özniteliği olarak kullanılacak modelin özellik adında hata yapılırsa, bunu ancak çalıştırma sırasında fark edebiliriz.

ASP.NET MVC, adından da anlaşılacağı üzere, özellikle formlar için HTML'in oluşturulmasını kolaylaştırmayı amaçlayan [HTML Helpers] adlı özel yöntemler sunar. Bu sınıflar kullanıldığında, yukarıdaki açılır listesi şu şekilde yazılır:


        <!-- açılır liste -->
        <tr>
          <td>Liste déroulante</td>
          <td>@Html.DropDownListFor(m => m.DropDownListField,
           new SelectList(@Model.DropDownListFieldItems, "Value", "Label"))
          </td>
</tr>

Açılır liste, 4-5. satırlarla oluşturulur. Kod, eskisine göre çok daha az karmaşıktır. Açılır liste için oluşturulan HTML kodu şöyledir:


        <!-- açılır liste -->
        <tr>
          <td>Liste déroulante</td>
          <td><select id="DropDownListField" name="DropDownListField"><option value="1">choix1</option>
<option selected="selected" value="2">choix2</option>
<option value="3">choix3</option>
</select></td>
</tr>
  • 4. satır: [name] özniteliği doğrudur;
  • 4-6. satırlar: seçenekler doğru şekilde oluşturulmuş ve doğru seçenek seçilmiştir.

Şimdi bu satırları oluşturan koda geri dönelim: HTML:


@Html.DropDownListFor(m => m.DropDownListField, new SelectList(@Model.DropDownListFieldItems, "Value", "Label"))
  • ilk parametre, m'nin görünüm şablonunu temsil ettiği ve m.DropDowListField'in bu şablonun bir özelliği olduğu lambda adlı bir işlevdir (adı budur). HTML kod oluşturucu, bu özelliğin adını kullanarak, oluşturulacak [select] öğesinin [id] ve [name] özniteliklerini oluşturacaktır. Var olmayan bir özellik kullanılırsa, hata derleme aşamasında ortaya çıkar; yürütme aşamasında değil. Bu, adlandırma hatalarının yalnızca yürütme aşamasında tespit edildiği önceki çözüme kıyasla bir iyileştirmedir;
  • ikinci parametre, açılır listeyi besleyecek öğe koleksiyonunu belirtmek için kullanılır. [SelectList] sınıfı bu koleksiyonu oluşturmaya olanak tanır:
    • birinci parametresi, herhangi bir öğe koleksiyonudur. Burada [Item] türünde bir koleksiyon bulunmaktadır;
    • ikinci parametresi, <option> etiketinin değerini sağlayacak öğelerin özelliğidir. Burada, bu, [Item] sınıfının [Value] özelliğidir;
    • üçüncü parametresi ise <option> etiketinin etiket metnini sağlayacak öğelerin özelliğidir. Burada, bu, [Item] sınıfının [Label] özelliğidir;
  • hangi seçeneğin seçilmesi gerektiğini belirlemek için (selected özniteliği), çerçeve bizim yaptığımız gibi hareket eder: seçeneğin değerini [DropDownListField] özelliğinin mevcut değeriyle karşılaştırır.

Şimdi kullanabileceğimiz diğer yöntemlere bakalım:

Radyo düğmeleri

Yeni kod şu şekildedir:


        <!-- radyo düğmeleri -->
        <tr>
          <td>Etes-vous marié(e)</td>
          <td>
            @{
    foreach (ApplicationModel.Item item in @Model.RadioButtonFieldItems)
    {
              @Html.RadioButtonFor(m => m.RadioButtonField, @item.Value)@item.Label
              <text/>
    }
            }
          </td>
</tr>

Oluşturulan HTML kodu şöyledir:


        <!-- radyo düğmeleri -->
        <tr>
          <td>Etes-vous marié(e)</td>
          <td>
<input id="RadioButtonField" name="RadioButtonField" type="radio" value="1" />oui              
<input checked="checked" id="RadioButtonField" name="RadioButtonField" type="radio" value="2" />non              
          </td>
</tr>

Kullanılan yöntem [Html.RadioButtonFor]'tir:

@Html.RadioButtonFor(m => m.RadioButtonField, @item.Value)
  • ilk parametre, radyo düğmesine atanacak modelin özelliğidir ([name] özniteliği);
  • ikinci parametre ise radyo düğmesine atanacak değerdir ([value] özniteliği).

Onay kutuları

Kod şu şekilde değişir:


        <!-- onay kutuları -->
        <tr>
          <td>Cases à cocher</td>
          <td>
            @{
              @Html.CheckBoxFor(m=>m.CheckBoxField1) @Model.CheckBoxesFieldItems[0].Label
              @Html.CheckBoxFor(m=>m.CheckBoxField2) @Model.CheckBoxesFieldItems[1].Label
              @Html.CheckBoxFor(m=>m.CheckBoxField3) @Model.CheckBoxesFieldItems[2].Label
            }
</td>

Onay kutularını oluşturmak için kullanılan yöntem [Html.CheckBoxFor]'tir:

Html.CheckBoxFor(m=>m.Propriété)

Parametre, onay kutusuyla ilişkilendirilecek modelin boole özelliğidir. [Propriété=true] ise onay kutusu işaretlenir. [Propriété=false] ise onay kutusu işaretlenmez. Her durumda, [value] özniteliğinin değeri true'tir. Oluşturulan HTML kodu şöyledir:


<input id="Propriété" name="Propriété" type="checkbox" value="true" />
<input name="Propriété" type="hidden" value="false" />
  • 1. satır: [value="true"] özniteliğine sahip onay kutusu;
  • 2. satır: [value="false"] özniteliğine sahip onay kutusuyla aynı adı ([Propriété]) taşıyan gizli bir alan (type=hidden). Neden aynı ada sahip iki [input] etiketi var? İki durum söz konusudur:
  • 1. satırdaki onay kutusu işaretliyse, gönderilen parametre dizesi Özellik=true&Özellik=false olur (1. ve 2. satırlar). [Propriété] özelliği yalnızca bir değer beklediğinden, çerçeve (framework) [true] değerini [Propriété]'e atadığını düşünebiliriz. Bunu başarmak için, alınan değerler arasında mantıksal bir OU işlemi yapması yeterlidir;
  • 1. satırdaki kutucuk işaretlenmemiş. Dolayısıyla gönderilen parametre dizisi Özellik=false şeklindedir (sadece 2. satır) ve bu durumda [Propriété] özelliği [false] değerini alır, ki bu doğrudur (kutucuk işaretlenmemiştir).

Tek satırlı giriş alanı

Yeni kod şu şekildedir:


          <!-- tek satırlık metin giriş alanı -->
          <tr>
            <td>Champ de saisie</td>
            <td>
              @Html.TextBoxFor(m => m.TextField, new { size = "30" })
            </td>
</tr>

Oluşturulan HTML kodu şöyledir:


          <!-- tek satırlık metin giriş alanı -->
          <tr>
            <td>Champ de saisie</td>
            <td>
              <input id="TextField" name="TextField" size="30" type="text" value="quelques mots" />
            </td>
</tr>

Kullanılan yöntem şöyledir:


@Html.TextBoxFor(m => m.TextField, new { size = "30" })
  • birinci parametre, giriş alanıyla ilişkili modelin özelliğini belirtir. Özelliğin adı, oluşturulan <input> etiketinin [name] ve [id] özniteliklerinde kullanılacak ve değeri [value] özniteliğine atanacaktır;
  • ikinci parametre, oluşturulan HTML etiketinin belirli özniteliklerini belirten anonim bir sınıftır; burada söz konusu olan öznitelik [size]'tir.

Şifre giriş alanı

Yeni kod şu şekildedir:


        <!-- şifre giriş alanı -->
        <tr>
          <td>Mot de passe</td>
          <td>
            @Html.PasswordFor(m => m.PasswordField, new { size = "15" })
          </td>
</tr>

Oluşturulan HTML kodu şöyledir:


        <!-- şifre giriş alanı -->
        <tr>
          <td>Mot de passe</td>
          <td>
            <input id="PasswordField" name="PasswordField" size="15" type="password" />
          </td>
</tr>

Kullanılan yöntem şöyledir:


@Html.PasswordFor(m => m.PasswordField, new { size = "15" })

Çalışma şekli, [Html.TexBoxFor] yöntemine benzerdir.

Çok satırlı giriş alanı

Yeni kod şöyledir:


        <!-- çok satırlı metin giriş alanı -->
        <tr>
          <td>Boîte de saisie</td>
          <td>
            @Html.TextAreaFor(m => m.TextAreaField, new { cols = "30", rows = "5" })
          </td>
</tr>

Oluşturulan HTML kodu şöyledir:


        <!-- çok satırlı metin giriş alanı -->
        <tr>
          <td>Boîte de saisie</td>
          <td>
            <textarea cols="30" id="TextAreaField" name="TextAreaField" rows="5">
ligne1
ligne2</textarea>
          </td>
</tr>

Kullanılan yöntem şöyledir:


@Html.TextAreaFor(m => m.TextAreaField, new { cols = "30", rows = "5" })

Çalışma şekli, [Html.TexBoxFor] yöntemine benzerdir.

Tek seçimli liste

Yeni kod şöyledir:


        <!-- tek seçimli liste -->
        <tr>
          <td>Liste à choix unique</td>
          <td>
          @Html.DropDownListFor(m => m.SimpleChoiceListField, new SelectList(@Model.SimpleChoiceListFieldItems, "Value", "Label"), new { size = "3" })
</tr>

ve oluşturulan HTML kodu şöyledir:


        <!-- tek seçimli liste -->
        <tr>
          <td>Liste à choix unique</td>
          <td>
          <select id="SimpleChoiceListField" name="SimpleChoiceListField" size="3">
<option value="1">liste1</option>
<option value="2">liste2</option>
<option selected="selected" value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
</tr>

[Html.DropDownListFor] yöntemini daha önce incelemiştik. Buradaki tek fark, 1'den farklı bir [size] özniteliğini belirtmek için kullanılan üçüncü parametredir. Açılır listeden [size=1] basit bir listeye geçişi sağlayan da bu özelliktir.

Çoklu seçim listesi

Yeni kod şu şekildedir:


        <!-- çoklu seçim listesi -->
        <tr>
          <td>Liste à choix multiple</td>
          <td>
          @Html.ListBoxFor(m => m.MultipleChoiceListField, new SelectList(@Model.MultipleChoiceListFieldItems, "Value", "Label"), new { size = "5" })
</tr>

ve oluşturulan HTML kodu şöyledir:


        <!-- çoklu seçim listesi -->
        <tr>
          <td>Liste à choix multiple</td>
          <td>
          <select id="MultipleChoiceListField" multiple="multiple" name="MultipleChoiceListField" size="5">
<option selected="selected" value="1">liste1</option>
<option value="2">liste2</option>
<option selected="selected" value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
</tr>

Yöntem


@Html.ListBoxFor(m => m.MultipleChoiceListField, new SelectList(@Model.MultipleChoiceListFieldItems, "Value", "Label"), new { size = "5" })

yöntemi, [Html.DropDownListFor] yöntemiyle aynı şekilde çalışır, ancak çoklu seçim listesi oluşturur. Seçilen seçenekler, [MultipleChoiceListField] tablosunda değeri (value özniteliği) bulunan seçeneklerdir.

<form> etiketi de bir yöntemle oluşturulabilir:


  @using (Html.BeginForm("Action09Post", "First"))
  {
...
  }

Oluşturulan HTML kodu şöyledir:


<form action="/First/Action09Post" method="post">    
    ...
</form>

Yöntem


Html.BeginForm("Action09Post", "First")

yönteminin ilk parametresi bir eylemin adı, ikinci parametresi ise bir denetleyicinin adıdır.

5.7.2. Eylemler ve model

Form, aşağıdaki [Action09Get] eylemi tarafından oluşturulacaktır:


    // Action09-GET
    [HttpGet]
    public ViewResult Action09Get(ApplicationModel application)
    {
      ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
      return View("Formulaire2", new ViewModel09(application));
}

6. satırda döndürülen görünüm, aşağıdaki [ViewModel09] modeliyle ilişkili olan [Formulaire2]'tir:


using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using Exemple_03.Models;

namespace Exemple_03.Models
{
  public class ViewModel09
  {
    // giriş alanları
    public string RadioButtonField { get; set; }
    public bool CheckBoxField1 { get; set; }
    public bool CheckBoxField2 { get; set; }
    public bool CheckBoxField3 { get; set; }
    public string TextField { get; set; }
    public string PasswordField { get; set; }
    public string TextAreaField { get; set; }
    public string DropDownListField { get; set; }
    public string SimpleChoiceListField { get; set; }
    public string[] MultipleChoiceListField { get; set; }

    // formda görüntülenecek koleksiyonlar
    public ApplicationModel.Item[] RadioButtonFieldItems { get; set; }
    public ApplicationModel.Item[] CheckBoxesFieldItems { get; set; }
    public ApplicationModel.Item[] DropDownListFieldItems { get; set; }
    public ApplicationModel.Item[] SimpleChoiceListFieldItems { get; set; }
    public ApplicationModel.Item[] MultipleChoiceListFieldItems { get; set; }

    // oluşturucular
    public ViewModel09()
    {
    }

    public ViewModel09(ApplicationModel application)
    {
      // koleksiyonların başlatılması
      RadioButtonFieldItems = application.RadioButtonFieldItems;
      CheckBoxesFieldItems = application.CheckBoxesFieldItems;
      DropDownListFieldItems = application.DropDownListFieldItems;
      SimpleChoiceListFieldItems = application.SimpleChoiceListFieldItems;
      MultipleChoiceListFieldItems = application.MultipleChoiceListFieldItems;
      // alanların başlatılması
      RadioButtonField = "2";
      CheckBoxField2 = true;
      TextField = "quelques mots";
      PasswordField = "secret";
      TextAreaField = "ligne1\nligne2";
      DropDownListField = "2";
      SimpleChoiceListField = "3";
      MultipleChoiceListField = new string[] { "1", "3" };
    }
  }
}

[ViewModel09], onay kutularının yönetimi açısından [ViewModel08]'ten farklıdır. Üç onay kutusundan oluşan bir tablo yerine, üç ayrı onay kutusu kullanılmıştır (11-13. satırlar).

Form, aşağıdaki [Action09Post] eylemi tarafından işlenecektir:


    // Action09-POST
    [HttpPost]
    public ViewResult Action09Post(ApplicationModel application, FormCollection posted)
    {
      ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
      ViewModel09 modèle = new ViewModel09(application);
      TryUpdateModel(modèle, posted);
      // gönderilmemiş değerlerin işlenmesi
      if (posted["SimpleChoiceListField"] == null)
      {
        modèle.SimpleChoiceListField = "";
      }
      if (posted["MultipleChoiceListField"] == null)
      {
        modèle.MultipleChoiceListField = new string[] { };
      }
      // form görüntüleme
      return View("Formulaire2", modèle);
}

[Action09Post] eylemi, iki nokta dışında [Action08Post] eylemiyle aynıdır:

  • 18. satır: [Formulaire] görünümü yerine [Formulaire2] görünümü kullanılır;
  • artık işaretlenmemiş onay kutularının yönetimi yoktur. Bu işlem artık [Html.CheckBoxFor] yöntemi tarafından doğru şekilde yönetilmektedir.

5.8. Modelin meta verilerinden form oluşturma

Form oluşturmak için yukarıdakilerden başka yöntemler de mevcuttur. Bunlardan biri, modelin bir alanına, MVC çerçevesinin hangi giriş etiketini oluşturması gerektiğini belirlemesini sağlayacak bilgileri ilişkilendirmektir. Bu bilgilere meta veriler denir.

Aşağıdaki [ViewModel10] görünüm modelini ele alalım:


using System;
using System.ComponentModel.DataAnnotations;
using System.Drawing;

namespace Exemple_03.Models
{
  public class ViewModel10
  {
    [Display(Name="Text")]
    [DataType(DataType.Text)]
    public string Text { get; set; }

    [Display(Name = "TextArea")]
    [DataType(DataType.MultilineText)]
    public string MultiLineText { get; set; }

    [Display(Name = "Number")]
    public int Number { get; set; }

    [Display(Name = "Decimal")]
    [UIHint("Decimal")]
    public double Decimal { get; set; }

    [Display(Name = "Tel")]
    [DataType(DataType.PhoneNumber)]
    public string Tel { get; set; }

    [Display(Name = "Date")]
    [DataType(DataType.Date)]
    public DateTime Date { get; set; }

    [Display(Name = "Time")]
    [DataType(DataType.Time)]
    public DateTime Time { get; set; }

    [Display(Name = "HiddenInput")]
    [UIHint("HiddenInput")]
    public string HiddenInput { get; set; }

    [Display(Name = "Boolean")]
    [UIHint("Boolean")]
    public bool Boolean { get; set; }

    [Display(Name = "Email")]
    [DataType(DataType.EmailAddress)]
    public string Email{ get; set; }

    [Display(Name = "Url")]
    [DataType(DataType.Url)]
    public string Url { get; set; }

    [Display(Name = "Password")]
    [DataType(DataType.Password)]
    public string Password { get; set; }

    [Display(Name = "Currency")]
    [DataType(DataType.Currency)]
    public double Currency { get; set; }

    [Display(Name = "CreditCard")]
    [DataType(DataType.CreditCard)]
    public string CreditCard { get; set; }

    // oluşturucu
    public ViewModel10()
    {
      Text = "tra la la";
      MultiLineText = "ligne1\nligne2";
      Number = 4;
      Decimal = 10.2;
      Tel = "0617181920";
      Date = DateTime.Now;
      Time = DateTime.Now;
      HiddenInput = "caché";
      Boolean = true;
      Email = "x@y.z";
      Url = "http://istia.univ-angers.fr";
      Password = "mdp";
      Currency = 4.2;
      CreditCard = "0123456789012345";
    }
  }
}

Meta veriler, [Display, DataType, UIHint] etiketlerinden oluşur.

Bu görünüm şablonu, aşağıdaki [Action10Get] eylemi tarafından oluşturulacaktır:


    // Eylem10-GET
    [HttpGet]
    public ViewResult Action10Get()
    {
      return View(new ViewModel10());
}

Yukarıdaki 5. satırda, [/First/Action10Get.cshtml ] eyleminin varsayılan görünümünden [ViewModel10] türündeki görünüm şablonunu görüntülemesi istenir. Bu görünüm şöyledir:


@model Exemple_03.Models.ViewModel10

@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action10Get</title>
</head>
<body>
  <h3>Formulaire ASP.NET MVC - 2</h3>
  @using (Html.BeginForm("Action10Post", "First"))
  {
    <table>
      <thead>
        <tr>
          <th>LabelFor</th>
          <th>EditorFor</th>
          <th>DisplayFor</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>@Html.LabelFor(m => m.Text)</td>
          <td>@Html.EditorFor(m => m.Text)</td>
          <td>@Html.DisplayFor(m => m.Text)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.MultiLineText)</td>
          <td>@Html.EditorFor(m => m.MultiLineText)</td>
          <td>@Html.DisplayFor(m => m.MultiLineText)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Number)</td>
          <td>@Html.EditorFor(m => m.Number)</td>
          <td>@Html.DisplayFor(m => m.Number)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Decimal)</td>
          <td>@Html.EditorFor(m => m.Decimal)</td>
          <td>@Html.DisplayFor(m => m.Decimal)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Tel)</td>
          <td>@Html.EditorFor(m => m.Tel)</td>
          <td>@Html.DisplayFor(m => m.Tel)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Date)</td>
          <td>@Html.EditorFor(m => m.Date)</td>
          <td>@Html.DisplayFor(m => m.Date)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Time)</td>
          <td>@Html.EditorFor(m => m.Time)</td>
          <td>@Html.DisplayFor(m => m.Time)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.HiddenInput)</td>
          <td>@Html.EditorFor(m => m.HiddenInput)</td>
          <td>@Html.DisplayFor(m => m.HiddenInput)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Boolean)</td>
          <td>@Html.EditorFor(m => m.Boolean)</td>
          <td>@Html.DisplayFor(m => m.Boolean)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Email)</td>
          <td>@Html.EditorFor(m => m.Email)</td>
          <td>@Html.DisplayFor(m => m.Email)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Url)</td>
          <td>@Html.EditorFor(m => m.Url)</td>
          <td>@Html.DisplayFor(m => m.Url)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Password)</td>
          <td>@Html.EditorFor(m => m.Password)</td>
          <td>@Html.DisplayFor(m => m.Password)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Currency)</td>
          <td>@Html.EditorFor(m => m.Currency)</td>
          <td>@Html.DisplayFor(m => m.Currency)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.CreditCard)</td>
          <td>@Html.EditorFor(m => m.CreditCard)</td>
          <td>@Html.DisplayFor(m => m.CreditCard)</td>
        </tr>
      </tbody>
    </table>
    <input type="submit" value="Valider" />
  }
</body>
</html>

Modelin her bir özelliği için şu yöntemi kullanıyoruz:

  • Html.LabelFor yöntemini kullanarak özelliğin [DisplayName] meta verisinin değerini görüntülüyoruz;
  • Html.EditorFor yöntemini, özelliğin değerini girmek için HTML etiketini oluşturmak amacıyla kullanıyoruz. Bu yöntem, özelliğin [DataType] ve [UIHint] meta verilerini kullanacaktır;
  • Html.DisplayFor, [DataType] meta verisinde belirtilen biçime göre özelliğin değerini görüntülemek için kullanılır.

İşte Chrome tarayıcısında bir yürütme örneği:

Image

Kullanılan tarayıcıya göre farklı sayfalar görüntülenebilir. Nitekim, oluşturulan görünüm, HTML'in HTML5 olarak adlandırılan 5. sürümüyle getirilen yeni etiketleri kullanır. Henüz tüm tarayıcılar bu sürümü desteklememektedir. Yukarıdaki örnekte, Chrome tarayıcısı bu sürümü kısmen desteklemektedir.

5.8.1. Formun [POST]'i

Formun [POST] etiketi, aşağıdaki [Action10Post] eylemi tarafından işlenir:


    // Eylem10-POST
    [HttpPost]
    public ContentResult Action10Post(ViewModel10 modèle)
    {
      string erreurs = getErrorMessagesFor(ModelState);
      string texte = string.Format("Contrôleur={0}, Action={1}, valide={2}, erreurs={3}", RouteData.Values["controller"], RouteData.Values["action"], ModelState.IsValid, erreurs);
      return Content(texte, "text/plain", Encoding.UTF8);
}
  • 3. satır: [Action10Post] eyleminin giriş modeli, gönderilen formdur;
  • 5. satır: Bu formun doğrulama hataları alınır;
  • 6. satır: Müşteriye gönderilecek metin yanıtı hazırlanır;
  • 7. satır: yanıt gönderilir.

Şimdi [ViewModel10] şablonunun özelliklerini tek tek inceleyelim ve ilgili meta verilerin, oluşturulan HTML şablonunu ve giriş alanlarının doğrulanmasını nasıl etkilediğini görelim.

5.8.2. [Text] özelliği

Tanım


    [Display(Name="Text")]
    [DataType(DataType.Text)]
    public string Text { get; set; }
...
Text = "tra la la";

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Text)</td>
        <td>@Html.EditorFor(m => m.Text)</td>
        <td>@Html.DisplayFor(m => m.Text)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="Text">Text</label></td>
        <td><input class="text-box single-line" id="Text" name="Text" type="text" value="tra la la" /></td>
        <td>tra la la</td>
</tr>

Yorumlar

  • [Html.LabelFor] yöntemi, 2. satırdaki <label> etiketini oluşturdu. [for] özniteliğinin değeri, [Html.LabelFor] yönteminin parametre özelliğinin adıdır

public string Text { get; set; }

Etiketinin başlangıcı ile sonu arasında görüntülenen metin, meta verinin metnidir


[Display(Name="Text")]

[Html.LabelFor] yöntemi her zaman bu şekilde çalışır. Diğer özellikler için bu konuya tekrar dönmeyeceğiz.

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini oluşturmuştur. Bu etiketin, [class] özniteliğine sahip olduğu ve bu özniteliğin CSS ve [text-box single-line] sınıflarını etikete atadığına dikkat edilmelidir. [id] ve [name] özniteliklerinin değeri, [Html.EditorFor] yönteminin parametre özelliğinin adı olan [Text]'tir. [type] özniteliği,

[DataType(DataType.Text)]
  • [Html.DisplayFor] yöntemi, 4. satırdaki metni oluşturdu. Bu, [Html.DisplayFor ] yönteminin parametre özelliğinin değeridir. Bu yöntem,

[DataType(DataType.Text)]

metaverisinden etkilenir; bu da değerin biçimlendirilmemiş metin olarak görüntülenmesine neden olur.

5.8.3. [MultiLineText] Özelliği

Tanım


    [Display(Name = "TextArea")]
    [DataType(DataType.MultilineText)]
public string MultiLineText { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.MultiLineText)</td>
        <td>@Html.EditorFor(m => m.MultiLineText)</td>
        <td>@Html.DisplayFor(m => m.MultiLineText)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="MultiLineText">TextArea</label></td>
        <td><textarea class="text-box multi-line" id="MultiLineText" name="MultiLineText">
ligne1
ligne2</textarea></td>
        <td>ligne1
ligne2</td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <textarea> etiketini oluşturdu. Bu etiketin, [class] özniteliğine sahip olduğu ve bu özniteliğin etikete CSS ve [text-box multi-line] sınıflarını atadığı unutulmamalıdır. [id] ve [name] özniteliklerinin değeri, [Html.EditorFor] yönteminin parametre özelliğinin adı olan [MultiLineText]'tir. Bu her zaman böyledir. Bundan sonra bu konuya değinmeyeceğiz. Oluşturulan etiket, <textarea> şeklindedir; bunun nedeni

[DataType(DataType.MultilineText)]

metaverisi, özelliğin çok satırlı bir metin olduğunu belirtmişti.

  • [Html.DisplayFor] yöntemi, 4-5. satırlardaki metni oluşturdu. Bu, [Html.DisplayFor ] yönteminin parametre özelliğinin değeridir.

5.8.4. [Number] özelliği

Tanım


    [Display(Name = "Number")]
public int Number { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Number)</td>
        <td>@Html.EditorFor(m => m.Number)</td>
        <td>@Html.DisplayFor(m => m.Number)</td>
</tr>

Görsel

 

HTML oluşturuldu


<tr>
        <td><label for="Number">Number</label></td>
        <td><input class="text-box single-line" data-val="true" data-val-number="Le champ Number doit être un nombre." data-val-required="Le champ Number est requis." id="Number" name="Number" type="number" value="4" /></td>
        <td>4</td>
      </tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ile [number] türünde oluşturmuştur. Görünüşe göre bunun tek nedeni, özelliğin türünün [int] olmasıdır. [data-val], [data-val-number] ve [data-val-required] öznitelikleri, HTML5 tarafından tanınmayan özniteliklerdir. Bunlar, istemci tarafında veri doğrulaması yapan bir JavaScript çerçevesinin tarafından kullanılır;
  • [Html.DisplayFor] yöntemi, 4. satırdaki metni, yani özelliğin değerini oluşturmuştur.

Doğrulama

[data-x] öznitelikleri, istemci tarafında veri doğrulamasını etkiler. İşte iki örnek:

Hatalı bir sayı girip doğrulama yapıldığında:

 

Yukarıda, doğrulama istemci tarafında gerçekleştirilmiştir. Hata düzeltilene kadar form gönderilmeyecektir.

Başka bir örnek: Hiçbir şey girilmediğinde:

Yukarıdaki [1] örneğinde, [Action10Post] bir hata bildiriyor. Belki de kontrol edilecek özellik üzerinde (bkz. sayfa 69) [Required] özniteliğini kullanarak daha önce bu davranışı elde ettiğimizi hatırlayabiliriz; burada söz konusu özellik [Number]'tir. Bu durumda ise bunu yapmak zorunda kalmadık.

5.8.5. [Decimal] özelliği

Tanım


    [Display(Name = "Decimal")]
    [UIHint("Decimal")]
public double Decimal { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Decimal)</td>
        <td>@Html.EditorFor(m => m.Decimal)</td>
        <td>@Html.DisplayFor(m => m.Decimal)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="Decimal">Decimal</label></td>
        <td><input class="text-box single-line" data-val="true" data-val-number="Le champ Decimal doit être un nombre." data-val-required="Le champ Decimal est requis." id="Decimal" name="Decimal" type="text" value="10,20" /></td>
        <td>10,20</td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ve [text] türüyle oluşturmuştur. Diğer öznitelikler, önceki [Number] özelliği için oluşturulanlarla aynıdır. Meta veri:

[UIHint("Decimal")]

bu nedenle, [Html.EditorFor] ve [Html.DisplayFor] yöntemlerinde özellik değeri iki ondalık basamakla görüntülenir

Doğrulama

Önceki durumun aksine, istemci tarafında herhangi bir doğrulama hatası bildirilmez. Hata yalnızca [Action10Post] eylemi tarafından bildirilir. Burada da, [Required] özniteliği eklenmesine gerek kalmadan ondalık sayı zorunludur.

5.8.6. [Tel] özelliği

Tanım


    [Display(Name = "Tel")]
    [DataType(DataType.PhoneNumber)]
public string Tel { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Tel)</td>
        <td>@Html.EditorFor(m => m.Tel)</td>
        <td>@Html.DisplayFor(m => m.Tel)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="Tel">Tel</label></td>
        <td><input class="text-box single-line" id="Tel" name="Tel" type="tel" value="0617181920" /></td>
        <td>0617181920</td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ve [tel] türüyle oluşturdu. Bu değer, aşağıdaki meta veri nedeniyle oluşturuldu:

[DataType(DataType.PhoneNumber)]

<input> etiketi için [tel] türü, HTML5'e göre yeni bir türdür. Chrome tarayıcısı bunu, [text] türüne sahip bir <input> etiketi olarak işledi.

Doğrulama

İster istemci tarafında ister sunucu tarafında herhangi bir doğrulama hatası bildirilmiyor. Herhangi bir şey girilebilir.

5.8.7. [Date] özelliği

Tanım


    [Display(Name = "Date")]
    [DataType(DataType.Date)]
public DateTime Date { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Date)</td>
        <td>@Html.EditorFor(m => m.Date)</td>
        <td>@Html.DisplayFor(m => m.Date)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="Date">Date</label></td>
        <td><input class="text-box single-line" data-val="true" data-val-date="Le champ Date doit être une date." data-val-required="Le champ Date est requis." id="Date" name="Date" type="date" value="11/10/2013" /></td>
        <td>11/10/2013</td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ve [date] türüyle oluşturmuştur. Bu değer, aşağıdaki meta veri nedeniyle oluşturulmuştur:

[DataType(DataType.Date)]

<input> etiketi için [date] türü, HTML5'e göre yeni bir özelliktir. Chrome tarayıcısı bunu tanır ve takvim aracılığıyla tarih girilmesine izin verir. Ayrıca, girilen tarih [jj/mm/aaaa] biçiminde görüntülenir; yani Chrome, tarih biçimini tarayıcının [locale] biçimine uyarlar.

  • [Html.DisplayFor] yöntemi de, yine [Date] meta verisinin varlığı nedeniyle tarihi [jj/mm/aaaa] biçiminde yazmıştır.

Doğrulama

[1] istemci tarafında geçersiz bir tarih bildirildiğinden, formun POST sunucuya gönderilmesi engelleniyor.

Tarihin eksikliği istemci tarafında bildirilmiyor, ancak sunucu tarafında bildiriliyor ([2]).

5.8.8. [Time] özelliği

Tanım


    [Display(Name = "Time")]
    [DataType(DataType.Time)]
public DateTime Time { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Time)</td>
        <td>@Html.EditorFor(m => m.Time)</td>
        <td>@Html.DisplayFor(m => m.Time)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="Time">Time</label></td>
        <td><input class="text-box single-line" data-val="true" data-val-required="Le champ Time est requis." id="Time" name="Time" type="time" value="11:17" /></td>
        <td>11:17</td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ve [time] türüyle oluşturmuştur. Bu değer, aşağıdaki meta veri nedeniyle oluşturulmuştur:

[DataType(DataType.Time)]

<input> etiketi için [time] türü, HTML5'e göre yeni bir özelliktir. Chrome tarayıcısı bunu tanır ve saatin [hh:mm] biçiminde girilmesine izin verir;

  • [Html.DisplayFor] yöntemi de, yine [Time] meta verisinin varlığı nedeniyle saati [hh:mm] biçiminde yazmıştır.

Doğrulama

Teknik olarak geçersiz bir saat girilmesi mümkün değildir. Saatin girilmemesi durumuna sunucu tarafında uyarı verilir:

 

5.8.9. [HiddenInput] özelliği

Tanım


    [Display(Name = "HiddenInput")]
    [UIHint("HiddenInput")]
public string HiddenInput { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.HiddenInput)</td>
        <td>@Html.EditorFor(m => m.HiddenInput)</td>
        <td>@Html.DisplayFor(m => m.HiddenInput)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="HiddenInput">HiddenInput</label></td>
        <td>cach&#233;<input id="HiddenInput" name="HiddenInput" type="hidden" value="gizli" /></td>
        <td>cach&#233;</td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ile oluşturdu; bu özniteliğin türü [hidden]'tir, yani gizli (ancak yine de gönderilen) bir alandır. Bu değer, şu meta veri nedeniyle oluşturulmuştur:

[UIHint("HiddenInput")]
  • [Html.DisplayFor] yöntemi, gizli alanın değerini yazmıştır.

5.8.10. [Boolean] özelliği

Tanım


    [Display(Name = "Boolean")]
public bool Boolean { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Boolean)</td>
        <td>@Html.EditorFor(m => m.Boolean)</td>
        <td>@Html.DisplayFor(m => m.Boolean)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="Boolean">Boolean</label></td>
        <td><input checked="checked" class="check-box" data-val="true" data-val-required="Le champ Boolean est requis." id="Boolean" name="Boolean" type="checkbox" value="true" /><input name="Boolean" type="hidden" value="false" /></td>
        <td><input checked="checked" class="check-box" disabled="disabled" type="checkbox" /></td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ile [checkbox] türünde, yani bir onay kutusu olarak oluşturdu. Bu değer, özelliğin boole türü olması nedeniyle oluşturuldu:

public bool Boolean { get; set; }
  • [Html.DisplayFor] yöntemi, 4. satırı oluşturdu; bu da bir onay kutusu (type özniteliği) olmakla birlikte devre dışı bırakılmış (disabled özniteliği).

5.8.11. [Email] özelliği

Tanım


    [Display(Name = "Email")]
    [DataType(DataType.EmailAddress)]
public string Email{ get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Email)</td>
        <td>@Html.EditorFor(m => m.Email)</td>
        <td>@Html.DisplayFor(m => m.Email)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="Email">Email</label></td>
        <td><input class="text-box single-line" id="Email" name="Email" type="email" value="x@y.z" /></td>
        <td><a href="mailto:x@y.z">x@y.z</a></td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ve [email] türüyle oluşturdu. Bu tür, HTML5'te yenidir. Bu tür, aşağıdaki meta veri nedeniyle oluşturulmuştur:

[DataType(DataType.EmailAddress)]

Chrome, bu türü [text] türü olarak işlemiş gibi görünüyor.

  • [Html.DisplayFor] yöntemi, 4. satırı oluşturdu: bir e-posta adresine bağlantı.

Doğrulama

[1] istemci tarafında geçersiz bir adres bildirildi:

Giriş yapılmaması herhangi bir hataya neden olmaz.

5.8.12. [Url] özelliği

Tanım


    [Display(Name = "Url")]
    [DataType(DataType.Url)]
public string Url { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Url)</td>
        <td>@Html.EditorFor(m => m.Url)</td>
        <td>@Html.DisplayFor(m => m.Url)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="Url">Url</label></td>
        <td><input class="text-box single-line" id="Url" name="Url" type="url" value="http://istia.univ-angers.fr" /></td>
        <td><a href="http://istia.univ-angers.fr">http://istia.univ-angers.fr</a></td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ve [url] türüyle oluşturdu. Bu tür, HTML5'te yenidir. Aşağıdaki meta veri nedeniyle oluşturulmuştur:

[DataType(DataType.Url)]

Chrome, bu türü [text] türü olarak işliyor gibi görünüyor.

  • [Html.DisplayFor] yöntemi, 4. satırı oluşturdu: URL'e bir bağlantı.

Doğrulama

URL tarafında geçersiz bir [1] bildirildi:

Giriş yapılmaması herhangi bir hataya neden olmaz.

5.8.13. [Password] özelliği

Tanım


    [Display(Name = "Password")]
    [DataType(DataType.Password)]
public string Password { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Password)</td>
        <td>@Html.EditorFor(m => m.Password)</td>
        <td>@Html.DisplayFor(m => m.Password)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="Password">Password</label></td>
        <td><input class="text-box single-line password" id="Password" name="Password" type="password" value="mdp" /></td>
        <td>mdp</td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ve [password] türüyle oluşturdu. Bu tür, aşağıdaki meta veri nedeniyle oluşturuldu:

[DataType(DataType.Password)]
  • [Html.DisplayFor] yöntemi 4. satırı oluşturmuştur.

5.8.14. [Currency] özelliği

Tanım


    [Display(Name = "Currency")]
    [DataType(DataType.Currency)]
public double Currency { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.Currency)</td>
        <td>@Html.EditorFor(m => m.Currency)</td>
        <td>@Html.DisplayFor(m => m.Currency)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="Currency">Currency</label></td>
        <td><input class="text-box single-line" data-val="true" data-val-number="Le champ Currency doit être un nombre." data-val-required="Le champ Currency est requis." id="Currency" name="Currency" type="text" value="4,2" /></td>
        <td>4,20 €</td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ve [text] türüyle oluşturdu;
  • [Html.DisplayFor] yöntemi, 4. satırı, para birimi sembolü içeren iki ondalık basamaklı bir sayı olarak oluşturdu. Bu biçim, aşağıdaki meta veri nedeniyle kullanıldı:

[DataType(DataType.Currency)]

Doğrulama

Sunucu tarafında geçersiz bir değer ([1]) veya değer eksikliği ([2]) bildirilir:

5.8.15. Özellik [CreditCard]

Tanım


    [Display(Name = "CreditCard")]
    [DataType(DataType.CreditCard)]
public string CreditCard { get; set; }

Görünüm


      <tr>
        <td>@Html.LabelFor(m => m.CreditCard)</td>
        <td>@Html.EditorFor(m => m.CreditCard)</td>
        <td>@Html.DisplayFor(m => m.CreditCard)</td>
</tr>

Görsel

 

HTML oluşturuldu


      <tr>
        <td><label for="CreditCard">CreditCard</label></td>
        <td><input class="text-box single-line" id="CreditCard" name="CreditCard" type="text" value="0123456789012345" /></td>
        <td>0123456789012345</td>
</tr>

Yorumlar

  • [Html.EditorFor] yöntemi, 3. satırdaki <input> etiketini, [type] özniteliği ve [text] türüyle oluşturmuştur. [Html.DisplayFor] yöntemi 4. satırı oluşturmuştur. Burada meta verinin ne işe yaradığı anlaşılmamaktadır:

[DataType(DataType.CreditCard)]

Doğrulama

Ne istemci tarafında ne de sunucu tarafında herhangi bir doğrulama yapılmamaktadır.

5.9. Formun doğrulanması

4.5. paragraf ve sonraki paragraflarda, bir eylemin modelinin doğrulanması sorununu daha önce ele almıştık. Bu konuyu bir form bağlamında tekrar ele alıyoruz:

  • kullanıcıya giriş hatalarını nasıl bildirebiliriz;
  • hataları kullanıcıya daha hızlı bildirmek için hem istemci tarafında hem de sunucu tarafında doğrulamalar yapmak.

5.9.1. Sunucu tarafında doğrulama

Aşağıdaki modeli ele alalım:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Net.Mail;

namespace Exemple_03.Models
{
  public class ViewModel11 : IValidatableObject
  {

    [Required(ErrorMessage = "Information requise")]
    [Display(Name = "Chaîne d'au moins quatre caractères")]
    [RegularExpression(@"^.{4,}$", ErrorMessage = "Information incorrecte")]
    public string Chaine1 { get; set; }

    [Display(Name = "Chaîne d'au plus quatre caractères")]
    [Required(ErrorMessage = "Information requise")]
    [RegularExpression(@"^.{1,4}$", ErrorMessage = "Information incorrecte")]
    public string Chaine2 { get; set; }

    [Required(ErrorMessage = "Information requise")]
    [Display(Name = "Chaîne de quatre caractères exactement")]
    [RegularExpression(@"^.{4,4}$", ErrorMessage = "Information incorrecte")]
    public string Chaine3 { get; set; }

    [Required(ErrorMessage = "Information requise")]
    [Display(Name = "Nombre entier")]
    public int Entier1 { get; set; }

    [Display(Name = "Nombre entier dans l'intervalle [1,100]")]
    [Required(ErrorMessage = "Information requise")]
    [Range(1, 100, ErrorMessage = "Information incorrecte")]
    public int Entier2 { get; set; }

    [Display(Name = "Nombre réel")]
    [Required(ErrorMessage = "Information requise")]
    public double Reel1 { get; set; }

    [Display(Name = "Nombre réel dans l'intervalle [10.2, 11.3]")]
    [Required(ErrorMessage = "Information requise")]
    [Range(10.2, 11.3, ErrorMessage = "Information incorrecte")]
    public double Reel2 { get; set; }

    [Display(Name = "Adresse mail")]
    [Required(ErrorMessage = "Information requise")]
    public string Email1 { get; set; }

    [Display(Name = "Date sous la forme dd/jj/aaaa")]
    [RegularExpression(@"\s*\d{2}/\d{2}/\d{4}\s*", ErrorMessage = "Information incorrecte")]
    [Required(ErrorMessage = "Information requise")]
    public string Regexp1 { get; set; }

    [Display(Name = "Date postérieure à celle d'aujourd'hui")]
    [Required(ErrorMessage = "Information requise")]
    [DataType(DataType.Date)]
    public DateTime Date1 { get; set; }

    // onay
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
      List<ValidationResult> résultats = new List<ValidationResult>();
      // Tarih 1
      if (Date1.Date <= DateTime.Now.Date)
      {
        résultats.Add(new ValidationResult("Information incorrecte", new string[] { "Date1" }));
      }
      // E-posta 1
      try
      {
        new MailAddress(Email1);
      }
      catch
      {
        résultats.Add(new ValidationResult("Information incorrecte", new string[] { "Email1" }));
      }
      // hata listesi döndürülüyor
      return résultats;
    }
  }
}

Bu model, aşağıdaki [Action11Get.cshtml] görünümüyle görüntülenecektir:


@model Exemple_03.Models.ViewModel11
@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action11Get</title>
  <link rel="stylesheet" href="~/Content/Site.css" />
</head>
<body>
  <h3>Formulaire ASP.NET MVC – Validation 1</h3>
  @using (Html.BeginForm("Action11Post", "First"))
  {
    <table>
      <thead>
        <tr>
          <th>Type attendu</th>
          <th>Valeur saisie</th>
          <th>Message d'erreur</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>@Html.LabelFor(m => m.Chaine1)</td>
          <td>@Html.EditorFor(m => m.Chaine1)</td>
          <td>@Html.ValidationMessageFor(m => m.Chaine1)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Chaine2)</td>
          <td>@Html.EditorFor(m => m.Chaine2)</td>
          <td>@Html.ValidationMessageFor(m => m.Chaine2)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Chaine3)</td>
          <td>@Html.EditorFor(m => m.Chaine3)</td>
          <td>@Html.ValidationMessageFor(m => m.Chaine3)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Entier1)</td>
          <td>@Html.EditorFor(m => m.Entier1)</td>
          <td>@Html.ValidationMessageFor(m => m.Entier1)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Entier2)</td>
          <td>@Html.EditorFor(m => m.Entier2)</td>
          <td>@Html.ValidationMessageFor(m => m.Entier2)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Reel1)</td>
          <td>@Html.EditorFor(m => m.Reel1)</td>
          <td>@Html.ValidationMessageFor(m => m.Reel1)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Reel2)</td>
          <td>@Html.EditorFor(m => m.Reel2)</td>
          <td>@Html.ValidationMessageFor(m => m.Reel2)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Email1)</td>
          <td>@Html.EditorFor(m => m.Email1)</td>
          <td>@Html.ValidationMessageFor(m => m.Email1)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Regexp1)</td>
          <td>@Html.EditorFor(m => m.Regexp1)</td>
          <td>@Html.ValidationMessageFor(m => m.Regexp1)</td>
        </tr>
        <tr>
          <td>@Html.LabelFor(m => m.Date1)</td>
          <td>@Html.EditorFor(m => m.Date1)</td>
          <td>@Html.ValidationMessageFor(m => m.Date1)</td>
        </tr>
      </tbody>
    </table>
    <p>
      <input type="submit" value="Valider" />
    </p>
  }
</body>
</html>
  • 12. satır: [Site.css] stil sayfasına referans verilir. Bu stil sayfası, varsayılan olarak formdaki giriş hatalarını vurgulamak için kullanılan sınıfları içerir;
  • 18-25. satırlar: üç sütunlu bir tablo:
    • 1. sütun, [Html.LabelFor] yöntemi ile metni görüntüler,
    • 2. sütun, [Html.EditorFor] yöntemi ile girilen veriyi görüntüler,
    • 3. sütun, [Html.ValidationMessageFor] yöntemi ile olası giriş hatalarını görüntüler;

[Action11Get] eylemi, formu görüntülemek için kullanılır:


    // Eylem11-GET
    [HttpGet]
    public ViewResult Action11Get()
    {
      return View("Action11Get", new ViewModel11());
}

[Action11Post] eylemi, olası giriş hatalarıyla birlikte formu yeniden görüntülemek için kullanılır:


    // Eylem11-POST
    [HttpPost]
    public ViewResult Action11Post(ViewModel11 modèle)
    {
      return View("Action11Get", modèle);
}
  • 3. satır: [ViewModel11] şablonu oluşturulur ve gönderilen değerlerle başlatılır. Bu sırada hatalar meydana gelebilir. Şablondaki her hatalı P özelliğine bir hata mesajı atanır. Formun [Html.ValidationMessageFor] yöntemi, bu mesajı almayı sağlar.

İşte bir yürütme örneği:

İşte başka bir örnek:

 

Her iki tarihin de hatalı olduğu (bugün 11/10/2013) ancak hataların bildirilmediği dikkat çekmektedir. Bu hatalar, şablondaki [Validate] yöntemi tarafından tespit edilmektedir:


    // doğrulama
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
      List<ValidationResult> résultats = new List<ValidationResult>();
      // Tarih 1
      if (Date1.Date <= DateTime.Now.Date)
      {
        résultats.Add(new ValidationResult("Information incorrecte", new string[] { "Date1" }));
      }
      // E-posta1
      try
      {
        new MailAddress(Email1);
      }
      catch
      {
        résultats.Add(new ValidationResult("Information incorrecte", new string[] { "Email1" }));
      }
      // Regexp1
      try
      {
        DateTime.ParseExact(Regexp1, "dd/MM/yyyy", CultureInfo.CreateSpecificCulture("fr-FR"));
      }
      catch
      {
        résultats.Add(new ValidationResult("Information incorrecte", new string[] { "Regexp1" }));
      }

      // hata listesi veriliyor
      return résultats;
}

[Validate] yöntemi, yalnızca tüm öznitelik doğrulamaları başarıyla tamamlandığında yürütülür. Son örnekte de bu durum görülmektedir:

 

5.9.2. İstemci tarafında doğrulama

Yukarıdaki tüm doğrulamalar sunucu tarafında gerçekleştirilmiştir. Dolayısıyla, kullanıcının hatalarını fark edebilmesi için istemci ile sunucu arasında bir gidiş-dönüş iletişimi gereklidir. İstemci tarafında doğrulama, kullanıcıya hatalarını mümkün olduğunca erken ve her halükarda POST işleminden önce bildirmek için JavaScript kodu kullanır. Bu işlem, tespit edilen tüm hatalar düzeltildikten sonra gerçekleştirilebilir.

Önceki [ViewModel11] şablonunu kullanıyoruz, ancak şimdi bunu aşağıdaki [Action12Get.cshtml] görünümüyle görüntülüyoruz:


@model Exemple_03.Models.ViewModel11
@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action12Get</title>
  <link rel="stylesheet" href="~/Content/Site.css" />
  <script type="text/javascript" src="~/Scripts/jquery-1.8.2.min.js" ></script>
  <script type="text/javascript" src="~/Scripts/jquery.validate.min.js" ></script>
  <script type="text/javascript" src="~/Scripts/jquery.validate.unobtrusive.min.js" ></script>
</head>
<body>
  <h3>Formulaire ASP.NET MVC - Validation 1</h3>
  @using (Html.BeginForm("Action11Post", "First"))
  {
    <table>
      <thead>
        <tr>
          <th>Type attendu</th>
          <th>Valeur saisie</th>
          <th>Message d'erreur</th>
        </tr>
      </thead>
      <tbody>
...
      </tbody>
    </table>
    <p>
      <input type="submit" value="Valider" />
    </p>
  }
</body>
</html>

Not: 13. satırda, jQuery sürümünü, kullandığınız Visual Studio sürümüne uygun hale getirin (aşağıya bakın).

İstemci tarafında doğrulama için, uygulamanın [Web.config] dosyasında aşağıdaki 3. satırın bulunması gerekir.


  <appSettings>
    ...
    <add key="ClientValidationEnabled" value="true" />
</appSettings>
  • 1-4. satırlar: [appSettings] bölümü, [Web.config] dosyasındaki [configuration] bölümünün doğrudan alt bölümü olmalıdır;

[Action12Get] görünümü, 13-15. satırlar hariç, önceki [Action11Get] görünümüyle aynıdır. Bu satırlar, görünümde istemci tarafında doğrulama için gerekli olan JavaScript komut dosyalarını içerir. Bu komut dosyaları, projenin [Scripts] klasöründe bulunur:

Her komut dosyasının normal bir sürümü ([.js]) ve minifiye edilmiş bir sürümü ([min.js]) vardır. Minifiye edilmiş sürüm daha hafiftir ancak okunamaz. Bu sürüm üretim ortamında kullanılır. Okunabilir sürüm ise geliştirme aşamasında kullanılır.

[Action12Get.cshtml] görünümü, aşağıdaki [Action12Get] eylemi tarafından görüntülenecektir:


    // Eylem12-GET
    [HttpGet]
    public ViewResult Action12Get()
    {
      return View("Action12Get", new ViewModel11());
}

Doldurulan form, aşağıdaki [Action12Post] eylemi tarafından işlenecektir:


    // Eylem12-POST
    [HttpPost]
    public ViewResult Action12Post(ViewModel11 modèle)
    {
      return View("Action12Get", modèle);
}

Bir örnek üzerinden bunun ne gibi bir değişiklik yarattığını görelim:

[1]'te bir karakter girildiğinde, beklenen değer en az dört karakterden oluşması gerektiği için [2]'teki hata mesajı görüntülenir. Böylece, her yeni karakter girildiğinde doğrulama yapılır. Dördüncü karakter girildiğinde hata mesajı kaybolur. Bu işlem tamamlandıktan sonra, formu onaylayalım:

URL ve [3] mesajları, [POST] işleminin gerçekleşmediğini göstermektedir. Ancak [Valider] düğmesine tıklandığında, istemci tarafındaki tüm doğrulama işlemleri tetiklendi ve yeni hata mesajları ortaya çıktı.

Örnek olarak, ilk giriş için oluşturulan HTML koduna bir göz atalım:


        <tr>
          <td><label for="Chaine1">Cha&#en az dört karakterden oluşan bir 238;ne</label></td>
          <td><input class="text-box single-line" data-val="true" data-val-regex="Information incorrecte" data-val-regex-pattern="^.{4,}$" data-val-required="Information requise" id="Chaine1" name="Chaine1" type="text" value="" /></td>
          <td><span class="field-validation-valid" data-valmsg-for="Chaine1" data-valmsg-replace="true"></span></td>
</tr>
  • 3. satırda şunlar yer alıyor:
    • giriş eksik olduğunda görüntülenen hata mesajı [data-val-required],
    • girişin hatalı olması durumunda görüntülenen hata mesajı [data-val-regex],
    • girilen dize için düzenli ifade [data-val-regex-pattern];
  • 4. satırda, olası hata mesajını görüntülemek için kullanılan diğer öznitelikler [data-x];

Oluşturulan etiketlerin [data-x] öznitelikleri, görünüme yerleştirdiğimiz JavaScript tarafından kullanılır. JavaScript yoksa, bu öznitelikler basitçe yok sayılır ve bu durumda istemci tarafında doğrulama yapılmaz. İşleyiş, önceki örnekteki gibidir. Bu nedenle bu tekniğe [unobtrusive] adı verilmiştir.

5.10. Gezinti ve eylem bağlantılarının yönetimi

Bir görünümde bağlantı yönetimini göstermek için aşağıdaki iki görünümü oluşturacağız:

  • [1] ve [2]'te iki gezinme bağlantısı vardır;
  • [3]'te ise formu gönderen bir eylem bağlantısı bulunmaktadır. Bu bağlantı gezinme amacıyla kullanılmaz.

Sayfa 1, aşağıdaki [Action16Get.cshtml] görünümü tarafından oluşturulur:


@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action16Get</title>
  <script>
    function postForm() {
      // belgedeki form alınır
      var form = document.forms[0];
      // gönderme
      form.submit();
    }
  </script>
</head>
<body>
  <h3>Navigation - page 1</h3>
  <h4>@ViewBag.info</h4>
  @using (Html.BeginForm("Action16Post", "Second"))
  {
    @Html.Label("data", "Tapez un texte")
    @Html.TextBox("data")
    <a href="javascript:postForm()">Valider</a>
  }
  <p>
    @Html.ActionLink("Page 2", "Action17Get", "Second")
  </p>
</body>
</html>
  • 22. satır: görünümü sunacak eylem tarafından başlatılan bir bilgi;
  • 23-28. satırlar: bir form;
  • 25. satır: [data] alanı için bir etiket;
  • 26. satır: [data] adlı bir giriş alanı;
  • 27. satır: [submit] türünde bir bağlantı. Üzerine tıklandığında, [postForm] adlı JavaScript işlevi çalıştırılır (href özniteliği). Bu işlev 12-17. satırlarda tanımlanmıştır;
  • 14. satır: belgenin 1. formuna, yani 23. satırdaki forma bir referans alınır;
  • 16. satır: Bu form gönderilir. Sonuç olarak, her şey sanki [submit] türünde bir düğmeye tıklanmış gibi gerçekleşir. Form, 23. satırda belirtilen denetleyiciye ve eyleme gönderilir;
  • satır 30: bir gezinme bağlantısı. Oluşturulan HTML kodu şöyledir:

    <a href="/Second/Action17Get">Page 2</a>

Kullanılan yöntem ActionLink(Metin, Eylem, Denetleyici) şeklindedir.

Sayfa 2, aşağıdaki [Action17Get.cshtml] görünümü tarafından oluşturulur:


@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Action17Get</title>
</head>
<body>
  <h3>Navigation - Page 2</h3>
  <h4>@ViewBag.info</h4>
  <p>
    @Html.ActionLink("Page 1", "Action16Get", "Second")
  </p>
</body>
</html>

Bu görünümleri oluşturan eylemler şunlardır:


      // Eylem16-GET
      [HttpGet]
      public ViewResult Action16Get()
      {
        ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
        return View("Action16Get");
      }

      // Eylem16-POST
      [HttpPost]
      public ViewResult Action16Post(string data)
      {
        ViewBag.info = string.Format("Contrôleur={0}, Action={1}, Data={2}", RouteData.Values["controller"], RouteData.Values["action"], data);
        return View("Action16Get");
      }

      // Eylem17-GET
      [HttpGet]
      public ViewResult Action17Get()
      {
        ViewBag.info = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
        return View();
}
  • 6. satırda, [Action16Get] eylemi, [Action16Get.cshtml] görünümünü, yani örneğin 1. sayfasını oluşturur. Bu görünümün şablonu [ViewBag]'tir (5. satır);
  • 19. satırda, [Action17Get] eylemi, [Action17Get.cshtml] görünümünü, yani örneğin 2. sayfasını oluşturur. Bu görünümün şablonu [ViewBag]'tir (21. satır);
  • satır 11: [Action16Post] eylemi, [Action16Get.cshtml] görünümünün formundaki POST'i işler. Bu eylem, [data] adlı parametreyi alır. Hatırlanacağı üzere bu, formdaki giriş alanının adıdır;
  • 13. satır: [ViewBag]'e bir bilgi girilir;
  • 14. satır: [Action16Get.cshtml] görünümü görüntülenir.

Okuyucunun bu örneği denemesi önerilir.