7. Bir uygulamanın Ajax ile uyarlanması ASP.NET MVC
7.1. Bir web uygulamasında AJAX'in yeri
Şu an için incelenen öğrenme örnekleri aşağıdaki mimariye sahiptir:
![]() |
Bir [Vue1] görünümünden bir [Vue2] görünümüne geçmek için tarayıcı:
- web uygulamasına bir istek gönderir;
- [Vue2] görünümünü alır ve bunu [Vue1] görünümünün yerine görüntüler.
Bu klasik şemadır:
- tarayıcıdan gelen istek;
- web sunucusu tarafından müşteriye yanıt olarak bir görünümün oluşturulması;
- tarayıcı tarafından bu yeni görünümün görüntülenmesi.
Tarayıcı ile web sunucusu arasında başka bir etkileşim biçimi daha vardır: AJAX (Asynchronous Javascript And Xml). Bu, aslında tarayıcı tarafından görüntülenen görünüm ile web sunucusu arasındaki etkileşimlerdir. Tarayıcı, yapmayı bildiği şeyi yapmaya devam eder, yani bir HTML görünümü görüntüler, ancak artık görüntülenen HTML görünümüne gömülü JavaScript tarafından kontrol edilir. Şema şu şekildedir:
![]() |
- [1]'te, tarayıcıda görüntülenen sayfada bir olay meydana gelir (bir düğmeye tıklama, metin değişikliği vb.). Bu olay, sayfaya gömülü JavaScript (JS) tarafından yakalanır;
- [2] aşamasında, JavaScript kodu, tarayıcının yapacağı gibi HTTP isteğini gönderir. İstek asenkron olarak gerçekleştirilir: kullanıcı, HTTP isteğine yanıt beklerken engellenmeden sayfayla etkileşime devam edebilir. İstek, klasik işleme sürecini izler. Bu isteği klasik bir istekten ayıran hiçbir (veya çok az) fark yoktur;
- [3]'te, JS istemcisine bir yanıt gönderilir. Tam bir HTML görünümü yerine, daha çok kısmi bir HTML görünümü, bir XML veya JSON (JavaScript Nesne Notasyonu) gönderilir;
- [4]'te, JavaScript bu yanıtı alır ve görüntülenen HTML sayfasının bir bölümünü güncellemek için kullanır.
Kullanıcı açısından, gördüğü içerik değiştiği için bir görünüm değişikliği söz konusudur. Ancak sayfanın tamamen yeniden yüklenmesi söz konusu değildir; sadece görüntülenen sayfanın kısmi bir değişikliği gerçekleşir. Bu, sayfaya akıcılık ve etkileşim kazandırır: sayfanın tamamen yeniden yüklenmemesi sayesinde, daha önce yönetilemeyen olayları yönetmek mümkün hale gelir. Örneğin, kullanıcı bir giriş kutusuna karakterler girdikçe ona bir seçenek listesi sunmak gibi. Her yeni karakter girildiğinde, sunucuya bir AJAX isteği gönderilir ve sunucu da başka öneriler gönderir. Ajax olmadan, bu tür bir giriş yardımı eskiden imkansızdı. Her karakter girildiğinde yeni bir sayfa yeniden yüklenemezdi.
7.2. JQuery ve JavaScript'in Temelleri
Sayfalarımıza sık sık JQuery JavaScript kütüphanesini ekledik. Bu kütüphanede şu satır yer alır:
<script type="text/javascript" src="~/Scripts/jquery-1.8.2.min.js"></script>
Not: jQuery sürümünü, kullandığınız Visual Studio sürümüne göre uyarlayın.
ASP.NET'in Ajax teknolojisi, MVC'i kullanır. Kendimiz de birkaç JQuery komut dosyası yazacağız. Bu nedenle, bu bölümdeki komut dosyalarını anlamak için bilmeniz gereken JQuery ile ilgili temel bilgileri şimdi sunacağız.
[Exemples] çözümümüzün içinde yeni bir [Exemple-04] projesi oluşturuyoruz:
![]() |
ASP.NET ve MVC ile Ajax'ı kullanmak için, [Web.config] ve [1] yapılandırma dosyalarında bir satır bulunmalıdır:
<appSettings>
...
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
3. satır, ASP.NET görünümlerinde Ajax kullanımına izin verir. Bu satır varsayılan olarak mevcuttur.
Yeni [2] projesinin [Content] klasöründe HTML ve [JQuery-01.html] dosyalarını oluşturuyoruz:
![]() |
Bu dosyanın içeriği şu şekilde olacaktır:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JQuery-01</title>
<script type="text/javascript" src="/Scripts/jquery-1.8.2.min.js"></script>
</head>
<body>
<h3>Rudiments de JQuery</h3>
<div id="element1">
Elément 1
</div>
</body>
</html>
- 6. satır: JQuery dosyasının içe aktarılması (sürümü, kullandığınız Visual Studio sürümüne göre uyarlayın);
- 10-12. satırlar: [element1] kimliğine sahip bir sayfa öğesi. Bu öğeyle biraz oynayacağız.
Bu dosyayı Google Chrome tarayıcısında görüntüleyelim: [4] ve [5]:
![]() |
Google Chrome'da [Ctrl-Maj-I] komutunu kullanarak geliştirici araçlarını [6] görüntüleyebiliriz. [Console] [7] sekmesi, JavaScript kodunu çalıştırmamızı sağlar. Aşağıda, girmeniz gereken JavaScript komutlarını ve bunların açıklamalarını veriyoruz.
JS | sonuç |
|
: [element1] kimliğine sahip tüm öğelerin koleksiyonunu döndürür; dolayısıyla normalde 0 veya 1 öğeden oluşan bir koleksiyon olur, çünkü bir sayfada iki özdeş kimlik bulunamaz (HTML). | ![]() |
|
: Koleksiyondaki tüm öğelere [blabla] metnini uygular. Bu işlem, sayfanın görüntülediği içeriği değiştirir | ![]() |
|
koleksiyondaki öğeleri gizler. [blabla] metni artık görüntülenmez. | ![]() |
|
: koleksiyonu yeniden görüntüler. Bu sayede, [element1] kimliğine sahip öğenin, öğeyi gizleyen CSS style='display: none;' özniteliğine sahip olduğunu görebiliriz. | |
|
: koleksiyondaki öğeleri görüntüler. [blabla] metni yeniden görünür. Bu görüntüyü sağlayan, CSS style='display : block;' özniteliğidir. | ![]() |
|
: koleksiyondaki tüm öğelere bir öznitelik atar. Buradaki öznitelik [style] ve değeri [color: red]'tir. [blabla] metni kırmızıya döner. | ![]() |
![]() | |
![]() |
Tüm bu işlemler sırasında tarayıcının URL değerinin değişmediğine dikkat edilmelidir. Web sunucusuyla herhangi bir veri alışverişi gerçekleşmemiştir. Her şey tarayıcının içinde gerçekleşmektedir. Şimdi sayfanın kaynak koduna bir göz atalım:
![]() |
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JQuery-01</title>
<script type="text/javascript" src="/Scripts/jquery-1.8.2.min.js"></script>
</head>
<body>
<h3>Rudiments de JQuery</h3>
<div id="element1">
Elément 1
</div>
</body>
</html>
Bu, başlangıçtaki metindir. 10-12. satırlardaki öğe üzerinde yaptığımız değişiklikleri hiçbir şekilde yansıtmamaktadır. JavaScript hata ayıklaması yaparken bunu akılda tutmak önemlidir. Bu nedenle, görüntülenen sayfanın kaynak kodunu görüntülemek çoğu zaman gereksizdir. Şu anda görüntülenen sayfanın kaynak kodunu öğrenmek için şu şekilde ilerleyeceğiz:
![]() |
Bundan sonra gelecek olan JS komut dosyalarını anlamak için yeterli bilgiye sahibiz.
7.3. Bir sayfayı akışla güncelleme HTML
7.3.1. Görünümler
Aşağıdaki uygulamayı inceleyeceğiz:
![]() |
- [1]'te, sayfanın yüklenme saati;
- [2]'te, A ve B adlı iki gerçek sayı üzerinde dört temel aritmetik işlem gerçekleştirilir;
- [3]'te, sunucunun yanıtı sayfanın belirli bir bölgesine yazılır;
- [4]'te, hesaplama zamanı. Bu, [5] sayfasının yüklenme zamanından farklıdır. Sayfanın yüklenme zamanı [1]'e eşittir; bu da [6] bölgesinin yeniden yüklenmediğini gösterir. Ayrıca, sayfanın URL ve [7] değerleri değişmemiştir.
7.3.2. Denetleyici, eylemler, model, görünüm
[Premier] adlı bir denetleyici oluşturuyoruz:
![]() |
İlk görünümü görüntülemek için şu [Action01Get] eylemini oluşturuyoruz:
[HttpGet]
public ViewResult Action01Get()
{
ViewModel01 modèle = new ViewModel01();
modèle.HeureChargement = DateTime.Now.ToString("hh:mm:ss");
return View(modèle);
}
- 4. satır: görünüm modelinin örneklenmesi;
- 5. satır: görünümün yüklenme zamanının başlatılması;
- 6. satır: [Action10Get.cshtml] görünümünün ve modelinin görüntülenmesi.
[ViewModel01] şablonu şöyledir:
![]() |
using System;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace Exemple_04.Models
{
[Bind(Exclude = "AplusB, AmoinsB, AmultipliéparB, AdiviséparB, Erreur, HeureChargement, HeureCalcul")]
public class ViewModel01
{
// form
[Required(ErrorMessage="Donnée requise")]
[Display(Name="Valeur de A")]
[Range(0, Double.MaxValue, ErrorMessage = "Tapez un nombre positif ou nul")]
public double A { get; set; }
[Required(ErrorMessage = "Donnée requise")]
[Display(Name = "Valeur de B")]
[Range(0, Double.MaxValue, ErrorMessage="Tapez un nombre positif ou nul")]
public double B { get; set; }
// sonuçlar
public string AplusB { get; set; }
public string AmoinsB { get; set; }
public string AmultipliéparB { get; set; }
public string AdiviséparB { get; set; }
public string Erreur { get; set; }
public string HeureChargement { get; set; }
public string HeureCalcul { get; set; }
}
}
- 11-14. satırlar: formun A değeri;
- 15-18. satırlar: formun B değeri;
- 21-24. satırlar: A ve B üzerinde yapılan dört aritmetik işlemin sonuçları;
- 25. satır: olası bir hatanın metni;
- 26. satır: görünümün tarayıcıya yüklenme saati;
- satır 27: 21-24. satırlardaki alanların hesaplandığı saat;
- 7. satır: Bu görünüm şablonu aynı zamanda bir eylem şablonudur. Tarayıcı tarafından gönderilmeyen alanlar bu eylem şablonundan hariç tutulur.
[Action01Get.cshtml] görünümü şöyledir:
![]() |
@model Exemple_04.Models.ViewModel01
@{
Layout = null;
AjaxOptions ajaxOpts = new AjaxOptions
{
UpdateTargetId = "résultats",
HttpMethod = "post",
Url = Url.Action("Action01Post"),
LoadingElementId = "loading",
LoadingElementDuration = 1000
};
}
<!DOCTYPE html>
<html lang="fr-FR">
<head>
<meta name="viewport" content="width=device-width" />
<title>Ajax-01</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>
<script type="text/javascript" src="~/Scripts/globalize/globalize.js"></script>
<script type="text/javascript" src="~/Scripts/globalize/cultures/globalize.culture.fr-FR.js"></script>
<script type="text/javascript" src="~/Scripts/globalize/cultures/globalize.culture.en-US.js"></script>
<script type="text/javascript" src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script type="text/javascript" src="~/Scripts/myScripts-01.js"></script>
</head>
<body>
<h2>Ajax - 01</h2>
<p><strong>Heure de chargement : @Model.HeureChargement</strong></p>
<h4>Opérations arithmétiques sur deux nombres réels A et B positifs ou nuls</h4>
@using (Ajax.BeginForm("Action01Post", null, ajaxOpts, new { id = "formulaire" }))
{
<table>
<thead>
<tr>
<th>@Html.LabelFor(m => m.A)</th>
<th>@Html.LabelFor(m => m.B)</th>
</tr>
</thead>
<tbody>
<tr>
<td>@Html.TextBoxFor(m => m.A)</td>
<td>@Html.TextBoxFor(m => m.B)</td>
</tr>
<tr>
<td>@Html.ValidationMessageFor(m => m.A)</td>
<td>@Html.ValidationMessageFor(m => m.B)</td>
</tr>
</tbody>
</table>
<p>
<input type="submit" value="Calculer" />
<img id="loading" style="display: none" src="~/Content/images/indicator.gif" />
<a href="javascript:postForm()">Calculer</a>
</p>
}
<hr />
<div id="résultats" />
</body>
</html>
- 1. satır: Görünümün modeli [ViewModel01] türündedir;
- 21. satır: Hem doğrulamalar hem de Ajax için JQuery gereklidir;
- satır 22-23: doğrulama kütüphaneleri;
- satır 24-26: uluslararasılaştırma kütüphaneleri;
- 27. satır: Ajax kütüphanesi;
- 28. satır: yerel bir JavaScript kütüphanesi;
- 33. satır: görünümün yüklenme saatinin görüntülenmesi;
- 35. satır: bir Ajax formu - buna daha sonra tekrar döneceğiz;
- 40-41. satırlar: A ve B sayılarının giriş alanlarının etiketleri;
- satır 46-47: A ve B sayılarının girilmesi;
- satır 50-51: A ve B sayılarının girilmesiyle ilgili hata mesajları;
- 56. satır: Formu gönderen düğme. Form, bir Ajax isteği ile gönderilecektir;
- 57. satır: Ajax isteği sırasında görüntülenen bekleme resmi;
- satır 58: Formu bir Ajax isteği ile göndermek için bir bağlantı;
- 62. satır: [résultats] kimliğine sahip bir <div> etiketi. Web sunucusu tarafından geri gönderilen HTML akışını buraya yerleştireceğiz.
Bu görünümde şu sayfa görüntülenir:
![]() |
Şimdi formu AJAX ile işleyen kodu inceleyelim:
...
@{
Layout = null;
AjaxOptions ajaxOpts = new AjaxOptions
{
UpdateTargetId = "résultats",
HttpMethod = "post",
Url = Url.Action("Action01Post"),
LoadingElementId = "loading",
LoadingElementDuration = 1000
};
}
...
@using (Ajax.BeginForm("Action01Post", null, ajaxOpts, new { id = "formulaire" }))
{
....
<p>
<input type="submit" value="Calculer" />
<img id="loading" style="display: none" src="~/Content/images/indicator.gif" />
<a href="javascript:postForm()">Calculer</a>
</p>
}
...
<div id="résultats" />
- 15. satır: [@Html.BeginForm] yerine [@Ajax.BeginForm] kullanılıyor. Bu yöntem birçok aşırı yüklemeyi destekler. Kullanılan yöntemin imzası şöyledir:
Ajax.BeginForm(string ActionName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string,object> htmlAttributes)
Burada aşağıdaki etkin parametreleri kullanıyoruz:
Action01Post: Formdaki POST öğesini işleyecek eylemin adı,
null: verilecek rota bilgisi yok,
ajaxOpts: Ajax çağrısının seçenekleri. Bunlar 6-10. satırlarda tanımlanmıştır,
new { id = "formulaire" }: Oluşturulan <form> etiketine [id='formulaire'] özniteliğini atamak için;
Kullanılan Ajax seçenekleri şunlardır:
- 8. satır: Ajax isteğinin hedefi;
- 7. satır: HTTP Ajax isteğinin yöntemi;
- 6. satır: Ajax isteğinin yanıtıyla güncellenecek sayfa bölgesinin kimliği;
- 9. satır: Ajax isteği sırasında görüntülenecek sayfa bölgesinin kimliği – genellikle bir bekleme görüntüsü. Burada 20. satır görüntülenecektir. Bu satır, beklemeyi simgeleyen bir animasyonlu görüntü içerir. Başlangıçta bu görüntü, [display : none] stiliyle gizlenmiştir;
- 10. satır: Animasyonlu görüntünün görüntülenmesinden önceki bekleme süresi (milisaniye cinsinden), burada 1 saniye.
Ajax formu tarafından oluşturulan HTML kodu şöyledir:
<form action="/Premier/Action01Post" data-ajax="true" data-ajax-loading="#loading" data-ajax-loading-duration="1000" data-ajax-method="post" data-ajax-mode="replace" data-ajax-update="#résultats" data-ajax-url="/Premier/Action01Post" id="formulaire" method="post"> <table>
...
<p>
<input type="submit" value="Calculer" />
<img id="loading" style="display: none" src="/Content/images/indicator.gif" />
<a href="javascript:postForm()">Calculer</a>
</p>
</form>
<hr />
<div id="résultats" />
- 1. satır: Oluşturulan <form> etiketi. Ajax isteğiyle ilişkilendirilen [AjaxOptions] türündeki nesnenin alan değerlerini yansıtan [data-ajax-attr] özniteliklerine dikkat edin. Bu öznitelikler Ajax kütüphanesi tarafından yönetilir. Bunlar olmadan <form> etiketi şu hale gelir:
<form action="/Premier/Action01Post" id="formulaire" method="post">
...
<p>
<input type="submit" value="Calculer" />
<img id="loading" style="display: none" src="/Content/images/indicator.gif" />
<a href="javascript:postForm()">Calculer</a>
</p>
</form>
Bu durumda, klasik bir HTML formuyla karşı karşıya kalırız. Kullanıcı tarayıcısında JavaScript'i devre dışı bırakırsa, bu kod çalıştırılacaktır. Bu durumda 5-6. satırlar kullanılmaz.
7.3.3. [Action01Post] eylemi
HTTP Ajax isteğini işleyen [Action01Post] eylemi şu şekildedir:
[HttpPost]
public PartialViewResult Action01Post(FormCollection postedData, SessionModel session)
{
// bekleme simülasyonu
Thread.Sleep(2000);
// eylem modelinin örneklenmesi
ViewModel01 modèle = new ViewModel01();
// hesaplama saati
modèle.HeureCalcul = DateTime.Now.ToString("hh:mm:ss");
// modelin güncellenmesi
TryUpdateModel(modèle, postedData);
if (!ModelState.IsValid)
{
// bir hata döndürülüyor
modèle.Erreur = getErrorMessagesFor(ModelState);
return PartialView("Action01Error", modèle);
}
// her iki seferde bir hata simülasyonu yapılır
int val = session.Randomizer.Next(2);
if (val == 0)
{
modèle.Erreur = "[erreur aléatoire]";
return PartialView("Action01Error", modèle);
}
// hesaplamalar
modèle.AplusB = string.Format("{0}", modèle.A + modèle.B);
modèle.AmoinsB = string.Format("{0}", modèle.A - modèle.B);
modèle.AmultipliéparB = string.Format("{0}", modèle.A * modèle.B);
modèle.AdiviséparB = string.Format("{0}", modèle.A / modèle.B);
// görünüm
return PartialView("Action01Success", modèle);
}
- 1. satır: eylem yalnızca bir [POST]'i işler;
- 2. satır: eylem şablonu olarak şunu kabul eder:
- [FormCollection postedData]: POST Ajax isteği tarafından gönderilen tüm değerler,
- [SessionModel session]: oturum öğeleri. Burada 4.10. paragrafta açıklanan bir teknik kullanılmaktadır;
- 2. satır: eylem, tam bir HTML sayfası değil, bir HTML parçası döndürecektir;
- 5. satır: Uzun süren bir Ajax eylemini simüle etmek için yapay olarak iki saniye bekleme yapılır;
- satır 7: [ViewModel01] türünde bir model oluşturulur;
- 9. satır: hesaplama saati başlatılır;
- 11. satır: [ViewModel01] türündeki model, gönderilen değerlerle güncellenmeye çalışılır. Hatırlatmak gerekirse, bu değerler ikidir: A ve B sayılarının değerleri;
- 12. satır: Bu güncellemenin başarılı olup olmadığı kontrol edilir;
- 15. satır: Hata durumunda, modelin [Erreur] alanı doldurulur;
- satır 16: [ViewModel01] şablonunu kullanarak [Action01Error.cshtml] kısmi görünümünü oluştururuz;
- satır 19-24: her iki seferde bir, bir hata simüle edilir;
- 19. satır: [0,1] aralığında rastgele bir tamsayı üretilir. Sayı üreteci oturumdan alınır;
- satır 20: üretilen değer 0 ise, bir hata simüle edilir;
- satır 22: hata mesajı şablona eklenir;
- satır 23: [ViewModel01] şablonunu kullanan [Action01Error.cshtml] kısmi görünümü döndürülür;
- 26-29. satırlar: A ve B sayıları üzerinde aritmetik hesaplamalar yapılır ve sonuçlar şablona karakter dizeleri biçiminde yerleştirilir;
- satır 31: [ViewModel01] şablonunu kullanan [Action01Success.cshtml] kısmi görünümü döndürülür;
7.3.4. [Action01Error] görünümü
[Action01Error.cshtml] görünümü şöyledir:
@model Exemple_04.Models.ViewModel01
<h4>Résultats</h4>
<p><strong>Heure de calcul : @Model.HeureCalcul</strong></p>
<p style="color: red;">Une erreur s'est produite : @Model.Erreur</p>
Bu HTML kısmi akışının, POST türündeki HTTP Ajax isteğine yanıt olarak gönderileceği ve sayfada [résultats] id'li bölgeye yerleştirileceği hatırlatılmalıdır. Tüm bu bilgiler, [Action01Get.cshtml] ana sayfasında kullanılan Ajax yapılandırmasından alınmıştır:
@model Exemple_04.Models.ViewModel01
@{
Layout = null;
AjaxOptions ajaxOpts = new AjaxOptions
{
UpdateTargetId = "résultats",
HttpMethod = "post",
Url = Url.Action("Action01Post"),
LoadingElementId = "loading",
LoadingElementDuration = 1000
};
}
İşte hatalı bir yanıt örneği:
![]() |
7.3.5. [Action01Success] görünümü
[Action01Success.cshtml] görünümü şöyledir:
@model Exemple_04.Models.ViewModel01
<h4>Résultats</h4>
<p><strong>Heure de calcul : @Model.HeureCalcul</strong></p>
<p>A+B=@Model.AplusB</p>
<p>A-B=@Model.AmoinsB</p>
<p>A*B=@Model.AmultipliéparB</p>
<p>A/B=@Model.AdiviséparB</p>
Yine burada, bu kısmi HTML akışı, POST türündeki HTTP Ajax isteğine yanıt olarak gönderilecek ve sayfada [résultats] kimliğine sahip bölgeye yerleştirilecektir:
![]() |
7.3.6. G şans yönetimi
[Action01Post]'in oturum kullandığını gördük. Oturum şablonu, aşağıdaki [SessionModel] türündedir:
using System;
namespace Exemple_03.Models
{
public class SessionModel
{
public Random Randomizer { get; set; }
}
}
Oturum, [Global.asax]'te başlatılır:
// Oturum
protected void Session_Start()
{
SessionModel sessionModel=new SessionModel();
sessionModel.Randomizer=new Random(DateTime.Now.Millisecond);
Session["data"] = sessionModel;
}
Oturumun bir modelle eşleştirilmesi [Application_Start]'te gerçekleştirilir:
protected void Application_Start()
{
...
// model bağlayıcıları
ModelBinders.Binders.Add(typeof(SessionModel), new SessionModelBinder());
}
[SessionModelBinder] sınıfı tanımlanmıştır.
7.3.7. Bekleme görüntüsünün yönetimi
@model Exemple_04.Models.ViewModel01
@{
Layout = null;
AjaxOptions ajaxOpts = new AjaxOptions
{
...
LoadingElementId = "loading",
LoadingElementDuration = 1000
};
}
...
<body>
...
@using (Ajax.BeginForm("Action01Post", null, ajaxOpts, new { id = "formulaire" }))
{
...
<p>
<input type="submit" value="Calculer" />
<img id="loading" style="display: none" src="~/Content/images/indicator.gif" />
<a href="javascript:postForm()">Calculer</a>
</p>
}
...
Ajax isteği başladığında, bir saniye sonra [loading] kimliğine sahip bölgenin 7. satırı görüntülenir ([ligne 8]). Bu bölge, başlangıçta gizlenmiş olan 21. satırın görüntüsüdür. Bu, aşağıdaki arayüzü oluşturur:
![]() |
7.3.8. [Calculer] bağlantısının yönetimi
Ana sayfa [Action01Get.cshtml]'teki [Calculer] bağlantısını inceleyelim:
<head>
<meta name="viewport" content="width=device-width" />
<title>Ajax-01</title>
...
<script type="text/javascript" src="~/Scripts/myScripts-01.js"></script>
</head>
<body>
<h2>Ajax - 01</h2>
<p><strong>Heure de chargement : @Model.HeureChargement</strong></p>
<h4>Opérations arithmétiques sur deux nombres réels A et B positifs ou nuls</h4>
@using (Ajax.BeginForm("Action01Post", null, ajaxOpts, new { id = "formulaire" }))
{
...
<p>
<input type="submit" value="Calculer" />
<img id="loading" style="display: none" src="~/Content/images/indicator.gif" />
<a href="javascript:postForm()">Calculer</a>
</p>
}
<hr />
<div id="résultats" />
- 18. satır: [Calculer] bağlantısına tıklandığında, JS [postForm] işlevi çalıştırılır. Bu işlev, [myScripts-01.js] dosyasının 5. satırında tanımlanmıştır. Bu komut dosyası şöyledir:
![]() |
function postForm() {
// JQuery ile manuel olarak bir Ajax çağrısı yapılıyor
var loading = $("#loading");
var formulaire = $("#formulaire");
var résultats = $('#sonuçlar');
$.ajax({
url: '/Premier/Action01Post',
type: 'POST',
data: formulaire.serialize(),
dataType: 'html',
begin: loading.show(),
success: function (data) {
loading.hide()
résultats.html(data);
}
})
}
// http://blog.instance-factory.com/?p=268
$.validator.methods.number = function (value, element) {
return this.optional(element) ||
!isNaN(Globalize.parseFloat(value));
}
$.validator.methods.date = function (value, element) {
return this.optional(element) ||
!isNaN(Globalize.parseDate(value));
}
jQuery.extend(jQuery.validator.methods, {
range: function (value, element, param) {
//Değeri ayrıştırmak için Globalization eklentisini kullanın
var val = Globalize.parseFloat(value);
return this.optional(element) || (
val >= param[0] && val <= param[1]);
}
});
19-37. satırlardaki işlevler, 6.1. paragrafta daha önce ele alınmıştı. Bu işlevler, sayfaların uluslararasılaştırılmasını yönetir. Bu konuya tekrar değinmeyeceğiz. 1-17. satırlarda, [Calculer] düğmesi durumunda projeye bağlı Ajax kütüphanesi tarafından gerçekleştirilen Ajax çağrısını manuel olarak yapıyoruz. Bunun için projeye bağlı JQuery kütüphanesini kullanıyoruz.
- 3. satır: [loading] kimliğine sahip bileşene bir referans. [$("#loading")], [loading] kimliğine sahip öğelerin koleksiyonunu döndürür. Bunlardan sadece bir tane vardır;
- 4. satır: [formulaire] kimliğine sahip bileşene bir referans;
- 5. satır: [résultats] kimliğine sahip bileşene bir referans;
- 6. satır: seçenekleriyle birlikte Ajax çağrısı;
- 7. satır: Ajax çağrısının hedefi olan URL;
- 8. satır: Kullanılan HTTP yöntemi;
- 9. satır: gönderilen veriler. [formulaire.serialize], [formulaire] kimlikli formun POST değerinden [A=val1&B=val2] dizesini oluşturur;
- 10. satır: Geri dönüşte beklenen veri türü. Sunucunun bir HTML akışı göndereceği bilinmektedir;
- 11. satır: İstek başladığında yürütülecek yöntem. Burada, [loading] kimlik numaralı bileşenin görüntülenmesi gerektiği belirtilir. Bu, bekleme sırasında gösterilen animasyonlu görüntüdür;
- 12. satır: Ajax isteği başarılı olduğunda yürütülecek yöntem. [data] parametresi, sunucudan gelen tam yanıttır. Bunun HTML akışı olduğu bilinmektedir;
- 13. satır: bekleme sinyalini gizliyoruz;
- 14. satır: [résultats] kimliğine sahip bileşen, [data] parametresindeki HTML değeriyle güncellenir.
Okuyucunun [Calculer] bağlantısını test etmesi önerilir. Bu bağlantı, bir hatası dışında [Calculer] düğmesi gibi çalışır. Bu bağlantı kullanıldıktan sonra, geçersiz A ve B değerleri gönderilebilir:
![]() |
- [1] ve [2]'te geçersiz değerler girilmiştir. Bu değerler, istemci tarafındaki doğrulayıcılar tarafından işaretlenmiştir;
- [3]'te, [Calculer] bağlantısına tıklandığında;
- [4]'te, [POST] hatası meydana gelmiştir, çünkü [4] yanıtı alınmaktadır.
Değerler geçersiz olduğunda ve [Calculer] düğmesine tıklandığında, sunucuya yönelik [POST] işlemi gerçekleşmez. Aynı durumda, [Calculer] bağlantısı kullanıldığında sunucuya [POST] isteği gönderilir. Dolayısıyla, [Calculer] düğmesinin, [Calculer] bağlantısıyla yeniden üretemediğimiz bir davranışı söz konusudur. Bu sorunu şu anda çözmeye çalışmak yerine, bunu daha sonraki bir örnek için saklıyoruz; bu örnek aynı zamanda istemci tarafındaki başka bir doğrulama sorununu da gösterecektir.
7.4. HTML sayfasının JSON akışıyla güncellenmesi
Önceki örnekte, web sunucusu HTTP Ajax isteğine bir HTML akışıyla yanıt vermişti. Bu akışta, HTML biçimlendirmesiyle birlikte veriler bulunuyordu. Şimdi önceki örneği, bu sefer yalnızca verileri içeren JSON (JavaScript Nesne Notasyonu) yanıtlarıyla ele alacağız. Bunun avantajı, bu şekilde daha az bayt aktarılmasıdır.
7.4.1. [Action02Get] eylemi
[Action02Get] eylemi, yeni uygulamanın giriş noktası olacaktır. Kod şöyledir:
@model Exemple_04.Models.ViewModel02
@{
Layout = null;
AjaxOptions ajaxOpts = new AjaxOptions
{
HttpMethod = "post",
Url = Url.Action("Action02Post"),
LoadingElementId = "loading",
LoadingElementDuration = 1000,
OnBegin = "OnBegin",
OnFailure = "OnFailure",
OnSuccess = "OnSuccess",
OnComplete = "OnComplete"
};
}
<!DOCTYPE html>
<html lang="fr-FR">
<head>
<meta name="viewport" content="width=device-width" />
<title>Ajax-02</title>
....
<script type="text/javascript" src="~/Scripts/myScripts-02.js"></script>
</head>
<body>
<h2>Ajax - 02</h2>
<p><strong>Heure de chargement : @Model.HeureChargement</strong></p>
<h4>Opérations arithmétiques sur deux nombres réels A et B positifs ou nuls</h4>
@using (Ajax.BeginForm("Action02Post", null, ajaxOpts, new { id = "formulaire" }))
{
...
<p>
<input type="submit" value="Calculer" />
<img id="loading" style="display: none" src="~/Content/images/indicator.gif" />
<a href="javascript:postForm()">Calculer</a>
</p>
}
<hr />
<div id="entete">
<h4>Résultats</h4>
<p><strong>Heure de calcul : <span id="heureCalcul"/></strong></p>
</div>
<div id="résultats">
<p>A+B=<span id="AplusB"/></p>
<p>A-B=<span id="AmoinsB"/></p>
<p>A*B=<span id="AmultipliéparB"/></p>
<p>A/B=<span id="AdiviséparB"/></p>
</div>
<div id="erreur">
<p style="color: red;">Une erreur s'est produite : <span id="msg"/></p>
</div>
</body>
</html>
- 4-14. satırlar: Ajax çağrısının seçenekleri;
- 10. satır: İsteğin başlatılması sırasında çalıştırılacak JS işlevi. Bu işlev, 24. satırda referans verilen JS dosyasında tanımlanmıştır;
- 11. satır: İsteğin başarısız olması durumunda çalıştırılacak JS işlevi;
- satır 12: İstek başarılı olduğunda çalıştırılacak JS işlevi;
- 13. satır: Ajax isteğinin sonucunu (başarısızlık veya başarı) aldıktan sonra çalıştırılacak JS işlevi;
- satır 40-43: [entete] kimliğine sahip bir bölge;
- satır 44-49: [résultats] kimliğine sahip bir bölge. Bu bölge, dört aritmetik işlemin sonuçlarını gösterecektir;
- satır 50-52: [erreur] kimliğine sahip bir bölge. Olası bir hata mesajını görüntüler.
7.4.2. [Action02Post] eylemi
Ajax isteği, aşağıdaki [Action02Post] eylemi tarafından işlenir:
[HttpPost]
public JsonResult Action02Post(FormCollection postedData, SessionModel session)
{
// bekleme simülasyonu
Thread.Sleep(2000);
// model doğrulama
ViewModel02 modèle = new ViewModel02();
// yükleme ve hesaplama süreleri
string HeureChargement = DateTime.Now.ToString("hh:mm:ss");
string HeureCalcul = DateTime.Now.ToString("hh:mm:ss");
// model güncellemesi
TryUpdateModel(modèle, postedData);
if (!ModelState.IsValid)
{
// bir hata döndürülüyor
return Json(new { Erreur = getErrorMessagesFor(ModelState), HeureCalcul = HeureCalcul });
}
// her iki seferden birinde bir hata simüle edilir
int val = session.Randomizer.Next(2);
if (val == 0)
{
// bir hata döndürülüyor
return Json(new { Erreur = "[erreur aléatoire]", HeureCalcul = HeureCalcul });
}
// hesaplamalar
string AplusB = string.Format("{0}", modèle.A + modèle.B);
string AmoinsB = string.Format("{0}", modèle.A - modèle.B);
string AmultipliéparB = string.Format("{0}", modèle.A * modèle.B);
string AdiviséparB = string.Format("{0}", modèle.A / modèle.B);
// sonuçlar döndürülür
return Json(new { Erreur = "", AplusB = AplusB, AmoinsB = AmoinsB, AmultipliéparB = AmultipliéparB, AdiviséparB = AdiviséparB, HeureCalcul = HeureCalcul });
}
- 2. satır: Yöntem, [JsonResult] türünde, yani JSON biçiminde bir metin döndürür;
- 16. satır: Bilgiler, JSON olarak serileştirilmiş anonim bir sınıf örneği biçiminde döndürülür. [getErrorMessagesFor] yöntemi daha önce tanıtılmıştı. Tarayıcıya gönderilen JSON dizesi şu şekilde olacaktır:
- 31. satır: Aritmetik sonuçlar için de aynı işlem uygulanır. Bu sefer, tarayıcıya gönderilen JSON dizesi şu şekilde olacaktır:
{"Erreur":"","AplusB":"4","AmoinsB":"-2","AmultipliéparB":"3","AdiviséparB":"0,333333333333333","HeureCalcul":"05:52:17"}
7.4.3. İstemci tarafındaki JavaScript kodu
İstemci tarayıcısına gönderilen HTML sayfasındaki Ajax çağrısının yapılandırmasını hatırlayalım:
AjaxOptions ajaxOpts = new AjaxOptions
{
HttpMethod = "post",
Url = Url.Action("Action02Post"),
LoadingElementId = "loading",
LoadingElementDuration = 1000,
OnBegin = "OnBegin",
OnFailure = "OnFailure",
OnSuccess = "OnSuccess",
OnComplete = "OnComplete"
};
7-10. satırlarda (= işaretinin sağında) referans verilen JS işlevleri, aşağıdaki [myScripts-02.js] dosyasında tanımlanmıştır:
// genel veriler
var entete;
var loading;
var résultats;
var erreur;
var heureCalcul;
var msg;
var AplusB;
var AmoinsB;
var AmultipliéparB;
var AdiviséparB;
var formulaire;
...
function postForm() {
...
}
// belge yüklendiğinde
$(document).ready(function () {
formulaire = $("#formulaire");
entete = $("#entete");
loading = $("#loading");
erreur = $("#erreur");
résultats = $('#sonuçlar');
heureCalcul = $("#heureCalcul");
msg = $("#msg");
AplusB = $("#AplusB");
AmoinsB = $("#AmoinsB");
AmultipliéparB = $("#AmultipliéparB");
AdiviséparB = $("#AdiviséparB");
// sayfanın bazı öğeleri önbelleğe alınır
entete.hide();
résultats.hide();
erreur.hide();
});
// başlangıç
function OnBegin() {
....
}
// isteğin sonu
function OnComplete() {
...
}
// başarılı
function OnSuccess(data) {
....
}
// hata
function OnFailure(request, error) {
...
}
- 19. satır: Sayfanın tarayıcıya yüklenmesi tamamlandığında JS işlevi çalıştırılır;
- 20-30. satırlar: Sayfada ilgilendiğimiz tüm bileşenlerin referansları alınır. Bir sayfada bileşen aramak bir maliyet gerektirir ve bu işlemin yalnızca bir kez yapılması tercih edilir;
- 33-35. satırlar: [entete], [résultats] ve [loading] bileşenleri gizlenir;
Ajax isteği başlatıldığında, aşağıdaki işlev yürütülür:
// başlatma
function OnBegin() {
// bekleme sinyali yanıyor
loading.show();
// sayfanın bazı öğeleri gizleniyor
entete.hide();
résultats.hide();
erreur.hide();
}
- 4. satır: [loading] bileşeni görüntülenir. Bu, hareketli görüntüdür;
- 6-8. satırlar: [entete], [résultats] ve [erreur] bileşenleri gizlenir;
Ajax isteği başarılı olursa, aşağıdaki JS kodu yürütülür:
// başarılı
function OnSuccess(data) {
// sonuçların görüntülenmesi
heureCalcul.text(data.HeureCalcul);
entete.show();
if (data.Erreur != '') {
msg.text(data.Erreur);
erreur.show();
return;
}
// hata yok
AplusB.text(data.AplusB);
AmoinsB.text(data.AmoinsB);
AmultipliéparB.text(data.AmultipliéparB);
AdiviséparB.text(data.AdiviséparB);
résultats.show();
}
Bu kodu anlamak için, tarayıcıya yanıt olarak gönderilebilecek iki metin olan JSON'i hatırlamak gerekir:
hata durumunda; aksi takdirde şu dize:
{"Erreur":"","AplusB":"4","AmoinsB":"-2","AmultipliéparB":"3","AdiviséparB":"0,333333333333333","HeureCalcul":"05:52:17"}
Bu dizeye [data] diyelim; [Erreur] alanının değeri, isteğe bağlı olarak [data.Erreur] veya [data["Erreur"]] notasyonu ile elde edilir. Aynı durum, JSON dizisindeki diğer alanlar için de geçerlidir. Ayrıca, X kimliğine sahip bir bileşene biçimlendirilmemiş bir metin atamak için [X.text(chaine)] yazılır. [OnSuccess] işlevinin koduna geri dönelim:
- 2. satır: [data], alınan JSON dizesidir;
- 4. satır: [heureCalcul] bileşeni değerini alır;
- 5. satır: [entete] bileşeni görüntülenir;
- satır 6: JSON dizisinin [Erreur] alanı test edilir;
- 7. satır: [msg] bileşenine değer atanır;
- satır 8: [erreur] bileşeni görüntülenir;
- 9. satır: hata durumu için işlem tamamlandı;
- 12. satır: [AplusB] bileşeni değerini alır;
- satır 13: [AmoinsB] bileşeni değerini alır;
- satır 14: [AmultipliéparB] bileşeni değerini alır;
- 15. satır: [AdiviséparB] bileşeni değerini alır;
- satır 16: [résultats] bileşeni görüntülenir.
HTTP Ajax isteğinin başarısız olması durumunda [OnFailure] işlevi çalıştırılacaktır. Bu başarısızlık, sunucu tarafından geri gönderilen HTTP kodu ile ölçülür. Örneğin, 500 [Internal Server Error] kodu, sunucunun isteği gerçekleştiremediğini gösterir. [OnFailure] işlevi şöyledir:
// hata
function OnFailure(request, error) {
alert("L'erreur suivante s'est produite :" + error);
}
Burada sadece meydana gelen hatayı içeren bir iletişim kutusu görüntüleniyor. Pratikte ise daha ayrıntılı bilgi verilmesi gerekir. Yakında başka bir çözüm sunacağız.
Son olarak, [OnComplete] işlevi, istek başarılı ya da başarısız olsun, tamamlandığında yürütülür.
// isteğin sonu
function OnComplete() {
// bekleme sinyali kapalı
loading.hide();
}
Bu noktada, [Action02Get.cshtml] görünümündeki Ajax çağrısının yapılandırmasının, bu farklı işlevlerin çağrılmasını sağladığını hatırlatmak isteriz:
AjaxOptions ajaxOpts = new AjaxOptions
{
...
OnBegin = "OnBegin",
OnFailure = "OnFailure",
OnSuccess = "OnSuccess",
OnComplete = "OnComplete"
};
7.4.4. [Calculer] bağlantısı
[Action02Get.cshtml] görünümündeki [Calculer] bağlantısının HTML kodu şu şekildedir:
<a href="javascript:postForm()">Calculer</a>
JS [postForm] işlevi, içe aktarılan [myScripts-02.js] dosyasında bulunur:
<script type="text/javascript" src="~/Scripts/myScripts-02.js"></script>
Kodu şöyledir:
function postForm() {
// JQuery ile manuel olarak bir Ajax çağrısı yapılıyor
$.ajax({
url: '/Premier/Action02Post',
type: 'POST',
data: formulaire.serialize(),
dataType: 'json',
beforeSend: OnBegin,
success: OnSuccess,
error: OnFailure,
complete: OnComplete
})
}
Daha önce de benzer bir kodla karşılaşmıştık.
- 4. satır: Ajax çağrısının hedefi olan URL;
- 5. satır: Ajax çağrısı tarafından kullanılan HTTP komutu;
- 6. satır: Gönderilen değerler. Bunlar, form değerlerinin serileştirilmesinin sonucudur. [formulaire] kimliği ile belirtilen bu form, [formulaire] değişkeni tarafından referans alınmaktadır. [data], [A=val1&B=val2] biçiminde bir karakter dizisi olacaktır;
- 7. satır: Beklenen yanıtın biçimlendirme türü. Bu, JSON biçiminde bir dizedir;
- 8. satır: Ajax çağrısı başlatıldığında çalıştırılacak JS işlevi;
- 9. satır: Ajax çağrısı başarılı olursa çalıştırılacak JS işlevi;
- 10. satır: Ajax çağrısı başarısız olursa çalıştırılacak JS işlevi;
- 11. satır: Sunucudan yanıt alındığında, yanıtın başarılı ya da hata olması fark etmeksizin çalıştırılacak JS işlevi.
Ajax çağrısının başarısız olması durumunu (10. satır) yöneten JavaScript işlevine geri dönelim. Ajax çağrısı çeşitli durumlarda başarısız olabilir; örneğin, sunucu [403 Forbidden], [404 Not Found], [500 Internal Server Error], [301 Moved Permanently] gibi bir hata kodu döndürdüğünde...
Önceki örnekte, [OnFailure] işlevi şöyledir:
// hata
function OnFailure(request, error) {
alert("L'erreur suivante s'est produite :" + error);
}
Genellikle, [error] nesnesinin görüntülenmesi ilginç bir bilgi sağlamaz. JQuery ile yapılan bir Ajax çağrısı kullanılıyorsa, aşağıdaki [OnFailure] yöntemi kullanılabilir;
// hata
function OnFailure(jqXHR) {
alert("Erreur : " + jqXHR.status + " " + jqXHR.statusText);
msg.html(jqXHR.responseText);
erreur.show();
}
JQuery [jqXHR] nesnesinin özellikleri arasında şunlar bulunur:
- responseText: sunucunun yanıt metni;
- status: sunucu tarafından döndürülen hata kodu;
- statusText: bu hata koduyla ilişkili metin.
- 3. satır: hata kodu ve buna ait açıklama görüntülenir;
- 4. satır: Sunucudan gelen HTML yanıtı, [msg] kimlikli bileşene yerleştirilir;
- 5. satır: [erreur] kimlikli bölge görüntülenir.
Bu hata işlevini test etmek için, [Action02Post] eyleminde yapay bir istisna oluşturacağız:
[HttpPost]
public JsonResult Action02Post(FormCollection postedData, SessionModel session)
{
// Ajax çağrısının hata işlevini test etmek için yapay bir istisna
throw new Exception();
// bekleme simülasyonu
Thread.Sleep(2000);
// model doğrulama
...
5. satır bir istisna oluşturur. Şimdi uygulamayı test edelim:
![]() |
[1] ve [2] için şu yanıtı alıyoruz:
![]() |
Sunucunun yanıtı, hatanın sunucu kodunun hangi satırında oluştuğunu görmemizi sağlar. Bu bilgi genellikle yararlıdır. Bundan sonra, Ajax çağrılarındaki hataları yönetmek için bu tekniği kullanacağız.
7.5. Tek Sayfalı Web Uygulaması
Ajax teknolojisi, tek sayfalık uygulamalar oluşturulmasına olanak tanır:
- ilk sayfa, tarayıcıdan gelen klasik bir istekle yüklenir;
- sonraki sayfalar ise Ajax çağrılarıyla elde edilir. Böylece, sonuç olarak tarayıcı hiçbir zaman URL adresinden ayrılmaz ve hiçbir zaman yeni bir sayfa yüklemez. Bu tür uygulamalara Tek Sayfalı Uygulama (APU) veya İngilizce'de Single Page Application (SPA) denir.
İşte bu tür bir uygulamanın basit bir örneği. Yeni uygulama iki görünüme sahip olacak:
![]() |
![]() |
- [1]'te, [Action03Get] eylemi bize ilk sayfayı, yani Sayfa 1'i sunar;
- [2]'te ise bir bağlantı, Ajax çağrısı sayesinde 2. sayfaya geçmemizi sağlar;
- [3]'te, URL değişmemiştir. Görüntülenen sayfa 2'dir;
- [4]'te, bir bağlantı sayesinde Ajax çağrısı yoluyla 1. sayfaya geri dönebiliriz;
- [5]'te, URL değişmemiştir. Görüntülenen sayfa 1'dir.
[Action03Get] eyleminin kodu şöyledir:
[HttpGet]
public ViewResult Action03Get()
{
return View();
}
- 4. satır: [Action03Get.cshtml] görünümü görüntülenir.
[Action03Get.cshtml] görünümü şöyledir:
![]() |
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Action03Get</title>
<script type="text/javascript" src="~/Scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
</head>
<body>
<h3>Ajax - 03 - Single Page Application</h3>
<div id="content">
@Html.Partial("Page1")
</div>
</body>
</html>
- 16-18. satırlar: [content] kimliğine sahip bir öğe. Farklı sayfalar bu öğe içinde görüntülenecektir;
- 17. satır: Varsayılan olarak ilk olarak [Page1.cshtml] sayfası görüntülenecektir.
[Page1.cshtml] sayfası şöyledir:
<h4>Page 1</h4>
<p>
@Ajax.ActionLink("Page 2", "Action04", new { Page = 2 }, new AjaxOptions() { UpdateTargetId = "content" })
</p>
- 1. satır: Sayfayı 2. sayfadan ayırt etmek için sayfa başlığı;
- 3. satır: Aşağıdaki parametrelere sahip bir Ajax bağlantısı:
- [Page 2] bağlantısının etiketi;
- [Action04] bağlantısının hedef eylemi;
- istenen URL'in parametreleri. Bu, [/Premier/Action04?Page=2] olacaktır;
- Ajax çağrısının seçenekleri. Burada, yalnızca sunucunun yanıtıyla güncellenecek bölgenin kimliği belirtilir. Diğer seçenekler için, varsa varsayılan değerler kullanılır. HTTP yönteminin varsayılan değeri GET'tir.
Bağlantıya tıklandığında ne olduğunu görelim. URL, [/Premier/Action04?Page=2] ile bir GET kullanılarak çağrılır. Ardından [Action04] eylemi yürütülür:
[HttpGet]
public PartialViewResult Action04(string page = "1")
{
string vue = "Page1";
if (page == "2")
{
vue = "Page2";
}
return PartialView(vue);
}
- 2. satır: eylem, kısmi bir HTML akışı döndürür;
- 2. satır: Eylemin şablonu [page] dizesidir. Oysa URL'in şu bilgiye sahip olduğu bilinmektedir: [/Premier/Action04?Page=2]. Şablonun büyük/küçük harf duyarlı olmadığı hatırlatılmalıdır;
- 4-8. satırlar: [vue], [Page2] değerini alacaktır;
- 9. satır: [Page2.cshtml] kısmi görünümü döndürülür.
[Page2.cshtml] kısmi görünümü şöyledir:
<h4>Page 2</h4>
<p>
@Ajax.ActionLink("Page 1", "Action04", new { Page = 1 }, new AjaxOptions() { UpdateTargetId = "content" })
</p>
Dolayısıyla sunucu, GET [/Premier/Action04?Page=2] Ajax çağrısına yanıt olarak yukarıdaki HTML akışını geri gönderir. Hatırlanacağı üzere, bu Ajax çağrısı bu yanıtı kullanarak [content] kimliğine sahip bölgeyi günceller (aşağıdaki 3. satır):
<h4>Page 1</h4>
<p>
@Ajax.ActionLink("Page 2", "Action04", new { Page = 2 }, new AjaxOptions() { UpdateTargetId = "content" })
</p>
Bu, aşağıdaki yeni görüntünün ortaya çıkmasına neden olur: [1]:
![]() |
Aynı mantığı izleyerek, [1]'teki [Page 1] bağlantısına tıklanmasının [2]'in görüntülenmesine neden olacağını görebiliriz.
ASP.NET MVC uygulamasının genel şemasına geri dönelim:
![]() |
HTML sayfalarında yer alan ve tarayıcıda çalıştırılan JavaScript sayesinde, kodu tarayıcıya aktarabilir ve aşağıdaki mimariyi elde edebiliriz:
![]() |
- [1]'te, ASP.NET MVC web katmanı, genellikle bir veritabanında barındırılan verilere erişim sağlayan bir web arayüzü haline gelmiştir. Sunulan görünümler yalnızca verileri içerir ve hiçbir HTML biçimlendirme öğesi (örneğin, XML veya JSON akışları) içermez;
- [2]'te: tarayıcı, [1] sunucusuyla aynı makinede bulunan veya bulunmayan bir web sunucusu tarafından sağlanan statik (yani dinamik olarak oluşturulmamış) görünümleri görüntüler. Bu statik sayfalar daha sonra, Javascript tarafından [1] web arayüzünden alınan verilerle zenginleştirilir;
- HTML sayfalarına gömülü JavaScript kodu katmanlar halinde yapılandırılabilir:
- [présentation] katmanı kullanıcı etkileşimlerinden sorumludur,
- [DAO] katmanı, [1] web sunucusu aracılığıyla verilere erişimden sorumludur,
- [métier] katmanı, daha önce [1] sunucusunda bulunan ve [2] tarayıcısına taşınan [métier] katmanına karşılık gelir;
Bu mimarinin avantajı, farklı becerileri devreye sokmasıdır:
- [1] web sunucusundaki kod, .NET becerilerini gerektirir ancak Javascript, HTML ve CSS becerilerini gerektirmez;
- tarayıcıya gömülü [2] kodu, Javascript, HTML ve CSS becerilerini gerektirir, ancak web sunucusunun teknolojisi ([1]) açısından fark etmez.
Bu mimari, farklı becerilere sahip ekiplerin paralel olarak çalışmasını kolaylaştırır. Özellikle Tek Sayfalı Uygulamalara çok uygundur.
7.6. Tek Sayfalı Web Uygulaması ve İstemci Tarafında Doğrulama
Daha önce Ajax-01 örneğiyle ilgili bir anomaliye değinmiştik. Konunun bağlamını hatırlatalım:
![]() |
- [1] ve [2]'te geçersiz değerler girilmiştir. Bu değerler, istemci tarafındaki doğrulayıcılar tarafından işaretlenmiştir;
- [3]'te, [Calculer] bağlantısına tıklandığında;
- [4]'te, [POST] hatası meydana gelmiştir, çünkü [4] yanıtı alınmaktadır.
Değerler geçersiz olduğunda ve [Calculer] düğmesine tıklandığında, sunucuya yönelik [POST] işlemi gerçekleşmez. Aynı durumda, [Calculer] bağlantısı kullanıldığında sunucuya [POST] isteği gönderilir. Dolayısıyla, [Calculer] düğmesinin, [Calculer] bağlantısıyla yeniden üretemediğimiz bir davranışı söz konusudur.
Bu örneği yeni bir bağlamda ele alacağız: Uygulama birden fazla görünüme sahip olacak ve az önce tanımladığımız [Application à Page Unique] türünde olacaktır.
7.6.1. Örnekteki görünümler
Örnekte birkaç görünüm bulunmaktadır:
![]() |
- [1]'te, [Action05Get] görünümü;
- [2]'te, [Formulaire05] kısmi görünümü;
- [3]'e, kısmi görünüm [Failure05];
![]() |
- [4]'te, [Success05] kısmi görünümü.
Uygulama tek sayfalıdır: bu sayfa, ilk istek sırasında tarayıcı tarafından yüklenir. Daha sonra Ajax çağrıları ile güncellenir.
Önceki sayfalar, aşağıdaki [cshtml] görünümleri tarafından oluşturulur:
![]() |
Başlangıçta yüklenen görünüm, aşağıdaki [Action05Get.cshtml] görünümüdür:
@model Exemple_04.Models.ViewModel05
@{
Layout = null;
}
<!DOCTYPE html>
<html lang="fr-FR">
<head>
<meta name="viewport" content="width=device-width" />
<title>Ajax-05</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>
<script type="text/javascript" src="~/Scripts/globalize/globalize.js"></script>
<script type="text/javascript" src="~/Scripts/globalize/cultures/globalize.culture.fr-FR.js"></script>
<script type="text/javascript" src="~/Scripts/globalize/cultures/globalize.culture.en-US.js"></script>
<script type="text/javascript" src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script type="text/javascript" src="~/Scripts/myScripts-05.js"></script>
</head>
<body>
<h2>Ajax - 05, Page unique - Validation formulaire côté client</h2>
<p><strong>Heure de chargement : @Model.HeureChargement</strong></p>
<h4>Opérations arithmétiques sur deux nombres réels A et B positifs ou nuls</h4>
<img id="loading" style="display: none" src="~/Content/images/indicator.gif" />
<div id="content">
@Html.Partial("Formulaire05", Model)
</div>
</body>
</html>
Aşağıdaki noktalara dikkat edilmelidir:
- 1. satır: Görünüm şablonu, birazdan tanıtacağımız [ViewModel05] türündedir;
- 13-19. satırlar: Ajax ve istemci tarafında doğrulama yapmak için gerekli JavaScript komut dosyaları burada yer almaktadır;
- 20. satır: [myScripts-05.js]'e kendi JavaScript işlevlerimizi ekleyeceğiz;
- 27. satır: Bekleme sırasında gösterilecek animasyonlu resim;
- 28-30. satırlar: [content] kimliğine sahip bir etiket. [Formulaire05, Success05, Failure05] kısmi görünümleri bu etiketin içine yerleştirilecektir;
- 29. satır: [Formulaire05] kısmi görünümünün eklenmesi.
[Action05Get] görünümü, başlangıç sayfasının [1] bölümünün görüntülenmesinden sorumludur:
![]() |
[Formulaire05] kısmi görünümü, yukarıdaki [2] bölümünü oluşturacaktır. Kod şöyledir:
@model Exemple_04.Models.ViewModel05
@using (Html.BeginForm("Action05Post", "Premier", FormMethod.Post, new { id = "formulaire" }))
{
<table>
<thead>
<tr>
<th>@Html.LabelFor(m => m.A)</th>
<th>@Html.LabelFor(m => m.B)</th>
</tr>
</thead>
<tbody>
<tr>
<td>@Html.TextBoxFor(m => m.A)</td>
<td>@Html.TextBoxFor(m => m.B)</td>
</tr>
<tr>
<td>@Html.ValidationMessageFor(m => m.A)</td>
<td>@Html.ValidationMessageFor(m => m.B)</td>
</tr>
</tbody>
</table>
<p>
<table>
<tbody>
<tr>
<td><a href="javascript:calculer()">Calculer</a>
</td>
<td style="width: 20px" />
<td><a href="javascript:effacer()">Effacer</a>
</td>
</tr>
</tbody>
</table>
</p>
}
- 1. satır: Kısmi görünüm, [ViewModel05] türünü şablon olarak kabul eder;
- 3. satır: [Html.BeginForm] yöntemi tarafından oluşturulan form. Bu form bir Ajax çağrısı ile gönderileceğinden, yöntemin ilk üç parametresi göz ardı edilecektir. Ancak kullanıcı tarayıcısında JavaScript'i devre dışı bırakmışsa durum farklıdır. Burada bu olasılığı göz ardı ediyoruz. Dördüncü parametre önemlidir. Formun kimliği [formulaire] olacaktır;
- 5-22. satırlar: A ve B sayılarının girildiği form;
- 27. satır: A ve B üzerinde dört aritmetik işlemin yürütülmesini başlatan bir JavaScript bağlantısı;
- 30. satır: Girişleri ve bunlarla ilişkili olası hata mesajlarını silen bir JavaScript bağlantısı.
Formda [submit] türünde bir düğme bulunmadığına dikkat edilmelidir. Girilen A ve B değerlerinin [Post] işlemini manuel olarak gerçekleştirmemiz gerekecektir.
Hata yoksa sonuçlar görüntülenir:
![]() |
Yukarıdaki [4] kısmı, aşağıdaki [Success05.cshtml] kısmi görünümü tarafından oluşturulur:
@model Exemple_04.Models.ViewModel05
<hr />
<p><strong>Heure de calcul : @Model.HeureCalcul</strong></p>
<p>A=@Model.A</p>
<p>B=@Model.B</p>
<h4>Résultats</h4>
<p>A+B=@Model.AplusB</p>
<p>A-B=@Model.AmoinsB</p>
<p>A*B=@Model.AmultipliéparB</p>
<p>A/B=@Model.AdiviséparB</p>
<p>
<a href="javascript:retourSaisies()">Retour aux saisies</a>
</p>
- 1. satır: [Success05.cshtml] kısmi görünümü, [ViewModel05] türünde bir şablon alır;
- 12. satır: girişlere geri dönmek için bir JavaScript bağlantısı.
Hata durumunda, başka bir kısmi görünüm olan [3] görüntülenir:
![]() |
Bu görünüm, aşağıdaki [Failure05.cshtml] kodu tarafından oluşturulur:
@model Exemple_04.Models.ViewModel05
<hr />
<p><strong>Heure de calcul : @Model.HeureCalcul</strong></p>
<p>A=@Model.A</p>
<p>B=@Model.B</p>
<h2>Les erreurs suivantes se sont produites</h2>
<ul>
@foreach (string msg in Model.Erreurs)
{
<li>@msg</li>
}
</ul>
<p>
<a href="javascript:retourSaisies()">Retour aux saisies</a>
</p>
- 1. satır: [Failure05.cshtml] kısmi görünümü, [ViewModel05] türünde bir şablon alır;
- 14. satır: girişlere geri dönmek için bir JavaScript bağlantısı.
7.6.2. Görünümlerin şablonu
Yukarıdaki tüm görünümler aynı [ViewModel05] şablonunu paylaşır:
![]() |
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace Exemple_04.Models
{
[Bind(Exclude = "AplusB, AmoinsB, AmultipliéparB, AdiviséparB, Erreurs, HeureChargement, HeureCalcul")]
public class ViewModel05
{
// form
[Required(ErrorMessage="Donnée A requise")]
[Display(Name="Valeur de A")]
[Range(0, Double.MaxValue, ErrorMessage = "Tapez un nombre A positif ou nul")]
public string A { get; set; }
[Required(ErrorMessage = "Donnée B requise")]
[Display(Name = "Valeur de B")]
[Range(0, Double.MaxValue, ErrorMessage="Tapez un nombre B positif ou nul")]
public string B { get; set; }
// sonuçlar
public string AplusB { get; set; }
public string AmoinsB { get; set; }
public string AmultipliéparB { get; set; }
public string AdiviséparB { get; set; }
public List<string> Erreurs { get; set; }
public string HeureChargement { get; set; }
public string HeureCalcul { get; set; }
}
}
Bu, birkaç küçük ayrıntı dışında daha önce tanıtılan [ViewModel01] şablonudur:
- 15. ve 19. satırlar: Giriş formunun ilk görüntülenmesinde, değeri 0 olan alanlar yerine boş giriş alanları görüntülemek amacıyla A ve B alanları artık [string] türündedir;
- 14. ve 18. satırlar: Bu, girilen değerin [Range] doğrulayıcısı ile kontrol edilmesini engellemez;
- 26. satır: [Failure05] görünümü tarafından görüntülenen bir hata mesajları listesi.
7.6.3. [Session] kapsamındaki veriler
7.3.6 numaralı paragrafta, oturum verilerinin aşağıdaki [SessionModel] modelinde kapsüllendiğini görmüştük:
![]() |
using System;
namespace Exemple_03.Models
{
public class SessionModel
{
// rastgele sayı üreteci
public Random Randomizer { get; set; }
}
}
Bu oturum şablonu, A ve B değerlerini içerecek şekilde genişletilmiştir:
using System;
namespace Exemple_03.Models
{
public class SessionModel
{
// rastgele sayı üreteci
public Random Randomizer { get; set; }
// A ve B değerleri
public string A { get; set; }
public string B { get; set; }
}
}
A ve B değerlerinin oturumda saklanması, aşağıdaki dizide gösterildiği gibi gerçekten de gereklidir:
İstek 1
![]() |
İstek 2
![]() |
[4]'te, [1]'te yapılan girişler bulunur. Ancak, iki ayrı HTTP isteği vardır. İki HTTP isteği arasındaki verilerin oturumda saklandığı bilinmektedir. İkinci isteğin, birinci istek tarafından gönderilen değerleri alabilmesi için, bu değerlerin oturuma kaydedilmesi gerekir.
7.6.4. [Action05Get] sunucu eylemi
[Action05Get] eylemi, başlangıçtaki tek sayfayı görüntüleyen eylemdir. Kodu şöyledir:
[HttpGet]
public ViewResult Action05Get()
{
ViewModel05 modèle = new ViewModel05();
modèle.HeureChargement = DateTime.Now.ToString("hh:mm:ss");
return View(modèle);
}
- 6. satır: Daha önce incelenen [Action05Get.cshtml] görünümü, [ViewModel05] türünde bir şablonla görüntülenir;
7.6.5. [Calculer] müşteri eylemi
Kullanıcının görünümlerle etkileşimlerini inceleyelim:
![]() |
[1] bağlantısı bir JavaScript bağlantısıdır:
<a href="javascript:calculer()">Calculer</a>
[calculer] JavaScript işlevi, [myScripts-05.js] dosyasında bulunur:
<script type="text/javascript" src="~/Scripts/myScripts-05.js"></script>
[calculer] JavaScript işlevinin kodu şöyledir:
// genel veriler
var content;
var loading;
function calculer() {
// öncelikle DOM ile ilgili referanslar
var formulaire = $("#formulaire");
// ardından formun doğrulanması
if (!formulaire.validate().form()) {
// form geçersiz - tamamlandı
return;
}
// Ajax çağrısı manuel olarak yapılıyor
$.ajax({
url: '/Premier/Action05FaireCalcul',
type: 'POST',
data: formulaire.serialize(),
dataType: 'html',
beforeSend: function () {
loading.show();
},
success: function (data) {
content.html(data);
},
complete: function () {
loading.hide();
},
error: function (jqXHR) {
// sunucu yanıtının görüntülenmesi
content.html(jqXHR.responseText);
}
})
}
function retourSaisies() {
...
}
function effacer() {
...
}
// belge yüklenirken
$(document).ready(function () {
// sayfanın çeşitli bileşenlerinin referansları alınır
loading = $("#loading");
content = $("#content");
// animasyonlu resim gizleniyor
loading.hide();
});
- Javascript kodunun her zaman tarayıcıda, istemci tarafında çalıştırıldığını hatırlatmak isteriz;
- 44. satır: Tek sayfanın ilk yüklemesi tamamlandığında çalıştırılan JS işlevi;
- 46. satır: id'si [loading] olan animasyonlu resme referans;
- 47. satır: id'si [content] olan bölgeye referans. [Formulaire05, Success05, Failure05] kısmi görünümlerini alan bu bölgedir;
- 2-3. satırlar: 46-47. satırlardaki değişkenler, diğer fonksiyonların bunlara erişebilmesi için küresel olarak tanımlanmıştır. Bir sayfada öğeleri aramanın bir maliyeti vardır (46-47. satırlar). Kaçınılabiliyorsa bu aramayı tekrarlamaya gerek yoktur;
- satır 5: [calculer] işlevi;
- 7. satır: Formdan bir referans alınır. [Formulaire05] kısmi görünümü, bu forma [formulaire] kimliğini vermiştir;
- 9. satır: Bu komut, formun istemci tarafındaki doğrulama kurallarını çalıştırır. 183. sayfada tespit edilen hatada eksik olan da budur. Bu yöntem, tek sayfa tarafından kullanılan [jquery.unobstrusive-ajax] kütüphanesi tarafından sağlanır:
<script type="text/javascript" src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
Form geçersiz olarak bildirildiğinde komut, [false] değerini döndürür;
- 11. satır: Form geçersizse sunucuya Ajax çağrısı yapılmaz;
- satır 14-32: sunucuya Ajax çağrısı yapılır;
- 15. satır: URL hedefi, [Action05FaireCalcul] sunucu eylemidir;
- 16. satır: [POST] aracılığıyla istenir;
- 17. satır: Gönderilen değerler. Bunlar formda girilen veriler, burada A ve B değerleri;
- 22-24. satırlar: Ajax çağrısı başarılı olursa, [calculer] işlevi, sunucu tarafından gönderilen HTML akışıyla [content] kimlikli bölgeyi günceller.
Bu HTML akışı, Ajax çağrısının hedeflediği [Action05FaireCalcul] eylemi tarafından gönderilen akıştır. Sunucu tarafındaki bu eylemin kodu şöyledir:
[HttpPost]
public PartialViewResult Action05FaireCalcul(FormCollection postedData, SessionModel session)
{
// şablon
ViewModel05 modèle = new ViewModel05();
// hesaplama saati
modèle.HeureCalcul = DateTime.Now.ToString("hh:mm:ss");
// şablonun güncellenmesi
TryUpdateModel(modèle, postedData);
if (!ModelState.IsValid)
{
// hata döndürülür
modèle.Erreurs = getListOfMessagesFor(ModelState);
return PartialView("Failure05", modèle);
}
...
}
- 1. satır: eylem yalnızca bir [post] kabul eder;
- 2. satır: Eylem, kısmi bir görünüm döndürür;
- 2. satır: Eylem, parametre olarak gönderilen değerleri (postedData) ve oturum modelini (session) alır;
- satır 5: Kısmi görünüm şablonu oluşturulur;
- 7. satır: Hesaplama saati ile güncellenir;
- 9. satır: Gönderilen değerler modele uygulanmaya çalışılır. Bunun üzerine modelin doğrulayıcıları çalıştırılır. Girilen veriler geçersizse istemci tarafındaki doğrulayıcılar POST'i engellediğine göre, neden bu zahmete girildiğini merak edebiliriz. Aslında, POST'in nereden geldiğinden emin değiliz. Belki de bizim kodumuzdan başka bir kod tarafından oluşturulmuş olabilir. Bu nedenle, her zaman sunucu tarafında da doğrulamalar yapılmalıdır;
- 10. satır: Doğrulayıcıların başarılı olup olmadığını test ediyoruz;
- 13. satır: Şablon geçersizse, bir hata listesiyle güncellenir. Sayfa 65’te açıklanan [GetErrorMessagesFor] yöntemine benzer olan [getListOfMessagesFor] iç yöntemine ayrıntılı olarak değinilmeyecektir;
- 14. satır: [Failure05] kısmi görünümü, şablonuyla birlikte görüntülenir. Bu görünümün kodunu tekrar verelim;
@model Exemple_04.Models.ViewModel05
<hr />
<p><strong>Heure de calcul : @Model.HeureCalcul</strong></p>
<p>A=@Model.A</p>
<p>B=@Model.B</p>
<h2>Les erreurs suivantes se sont produites</h2>
<ul>
@foreach (string msg in Model.Erreurs)
{
<li>@msg</li>
}
</ul>
<p>
<a href="javascript:retourSaisies()">Retour aux saisies</a>
</p>
- 7-12. satırlar: Şablondaki hata listesi, <ul> etiketiyle görüntülenir.
JS işlevinin, [calculer] işlevinin[Post] işlevinin, [Action05FaireCalcul] sunucu eylemi aracılığıyla bu HTML akışını [content] kimliğine sahip bölgeye yerleştireceğini hatırlayalım. Sonuç şuna benzer:
![]() |
[Action05FaireCalcul] eyleminin kodunu incelemeye devam edelim:
[HttpPost]
public PartialViewResult Action05FaireCalcul(FormCollection postedData, SessionModel session)
{
// şablon
ViewModel05 modèle = new ViewModel05();
...
// A ve B değerleri oturuma kaydediliyor
session.A = modèle.A;
session.B = modèle.B;
// Şu ana kadar hata yok
List<string> erreurs = new List<string>();
// her iki denemeden birinde bir hata simüle ediliyor
int val = session.Randomizer.Next(2);
if (val == 0)
{
erreurs.Add("[erreur aléatoire]");
}
if (erreurs.Count != 0)
{
modèle.Erreurs = erreurs;
return PartialView("Failure05", modèle);
}
// hesaplamalar
double A = double.Parse(modèle.A);
double B = double.Parse(modèle.B);
modèle.AplusB = string.Format("{0}", A + B);
modèle.AmoinsB = string.Format("{0}", A - B);
modèle.AmultipliéparB = string.Format("{0}", A * B);
modèle.AdiviséparB = string.Format("{0}", A / B);
// görünüm
return PartialView("Success05", modèle);
}
- 7. satır: şablon geçerli olarak tanımlandı;
- 8-9. satırlar: Girilen A ve B değerleri oturuma kaydedilir. Bunları takip edecek sorguda bulabilmek istiyoruz;
- 11-22. satırlar: her iki seferde bir rastgele bir hata üretilir;
- 24-29. satırlar: Girilen gerçek sayılar üzerinde dört temel aritmetik işlem gerçekleştirilir;
- satır 31: [Success05] kısmi görünümü, şablonuyla birlikte döndürülür. Bu kısmi görünüm şöyledir:
@model Exemple_04.Models.ViewModel05
<hr />
<p><strong>Heure de calcul : @Model.HeureCalcul</strong></p>
<p>A=@Model.A</p>
<p>B=@Model.B</p>
<h4>Résultats</h4>
<p>A+B=@Model.AplusB</p>
<p>A-B=@Model.AmoinsB</p>
<p>A*B=@Model.AmultipliéparB</p>
<p>A/B=@Model.AdiviséparB</p>
<p>
<a href="javascript:retourSaisies()">Retour aux saisies</a>
</p>
Hatırlanacağı üzere, JS [calculer] işlevinin[Post]'in kaynağı olan ve [Action05FaireCalcul] sunucu eylemine ait olan JS [calculer] fonksiyonu, bu HTML akışını [content] kimlik bölgesine yerleştirecektir. Sonuç şuna benzer:
![]() |
7.6.6. [Effacer] istemci eylemi
[Effacer] JavaScript bağlantısı, formu başlangıç durumuna geri getirir:
![]() | ![]() |
Formda, JS [Effacer] bağlantısı şu şekilde tanımlanmıştır:
<a href="javascript:effacer()">Effacer</a>
JS [effacer] işlevi, [myScripts-05.js] dosyasında şu şekilde tanımlanmıştır:
// genel veriler
var content;
var loading;
function calculer() {
...
}
function retourSaisies() {
...
}
function effacer() {
// önce DOM'teki referanslar
var formulaire = $("#formulaire");
var A = $("#A");
var B = $("#B");
// girişlere geçerli değerler atanır
A.val("0");
B.val("0");
// ardından formu onaylayarak
// olası hata mesajlarını ortadan kaldırmak için
formulaire.validate().form();
// ardından giriş alanlarına boş dizeler atanır
A.val("");
B.val("");
}
// belge yüklendiğinde
$(document).ready(function () {
// sayfanın çeşitli bileşenlerinin referanslarını alırız
loading = $("#loading");
content = $("#content");
// animasyonlu resim gizlenir
loading.hide();
});
- 15-17. satırlar: DOM dosyasının çeşitli öğelerine ilişkin referanslar alınır (Belge Nesne Modeli);
- 19-20. satırlar: A ve B sayı giriş alanlarına geçerli değerler girilir;
- 23. satır: istemci tarafındaki doğrulayıcılar çalıştırılır. A ve B değerleri geçerli olduğundan, bu işlem görüntülenebilecek olası hata mesajlarının ortadan kalkmasını sağlar;
- 25-26. satırlar: A ve B sayı giriş alanlarına boş dizeler girilir;
7.6.7. [Retour aux Saisies] istemci eylemi
[Retour aux Saisies] JavaScript bağlantısı, sonuçlar alındıktan sonra forma geri dönmeyi sağlar:
![]() | ![]() |
Formda, JS [Retour aux Saisies] bağlantısı şu şekilde tanımlanmıştır:
<a href="javascript:retourSaisies()">Retour aux saisies</a>
JS [retourSaisies] işlevi, [myScripts-05.js] dosyasında şu şekilde tanımlanmıştır:
// genel veriler
var content;
var loading;
function calculer() {
...
}
function retourSaisies() {
// manuel olarak bir Ajax çağrısı yapılır
$.ajax({
url: '/Premier/Action05RetourSaisies',
type: 'POST',
dataType: 'html',
beforeSend: function () {
loading.show();
},
success: function (data) {
content.html(data);
},
complete: function () {
loading.hide();
// IMPORTANT !! doğrulama
$.validator.unobtrusive.parse($("#formulaire"));
},
error: function (jqXHR) {
content.html(jqXHR.responseText);
}
})
}
function effacer() {
...
}
// belge yüklendiğinde
$(document).ready(function () {
// sayfanın çeşitli bileşenlerinin referansları alınır
loading = $("#loading");
content = $("#content");
// animasyonlu görüntüyü önbelleğe alıyoruz
loading.hide();
});
- 11-29. satırlar: bir Ajax çağrısı;
- 12. satır: hedef URL;
- 13. satır: HTTP POST komutuyla çağrılacaktır. Bu, POST parametreleri içermeyen bir POST'tir. Bu nedenle, şu tür bir satır bulunmaz:
Ajax çağrısında bulunmaz;
- 14. satır: sunucudan beklenen akış, HTML akışıdır;
- 18-20. satırlar: Bu HTML akışı, [content] kimliğine sahip bölgeyi güncellemek için kullanılacak;
[Action05RetourSaisies] sunucu eylemi şu şekildedir:
[HttpPost]
public PartialViewResult Action05RetourSaisies(SessionModel session)
{
// görünüm
return PartialView("Formulaire05", new ViewModel05() { A = session.A, B = session.B });
}
- 2. satır: eylem, daha önce girilen A ve B değerlerini kaydettiğimiz oturum şablonunu parametre olarak alır;
- 5. satır: [Formulaire05] kısmi görünümünü, [ViewModel05] türünde bir şablonla döndürürüz; bu şablonda, A ve B alanlarını oturumdan alınan A ve B değerleriyle başlatmaya özen gösteririz;
Şimdi [retourSaisies] adlı JavaScript işlevinin koduna geri dönelim:
function retourSaisies() {
// manuel olarak bir Ajax çağrısı yapılıyor
$.ajax({
url: '/Premier/Action05RetourSaisies',
type: 'POST',
dataType: 'html',
beforeSend: function () {
loading.show();
},
success: function (data) {
content.html(data);
},
complete: function () {
loading.hide();
// IMPORTANT !! doğrulama
$.validator.unobtrusive.parse($("#formulaire"));
},
error: function (jqXHR) {
content.html(jqXHR.responseText);
}
})
}
- 13. satır: Ajax çağrısı tamamlandığında yürütülen yöntem;
- 14. satır: Bekleme animasyonu gizlenir;
- 16. satır: İnternette bulduğum ve benim için biraz anlaşılması zor olan bir komut; bu komut, şu sorunu çözmek için kullanıldı: [Retour aux saisies] bağlantısı tarafından görüntülenen formda, istemci tarafındaki doğrulama işlevleri artık çalışmıyordu. JS ve [jquery.unobtrusive-ajax] kütüphaneleri hakkında bilgi ararken, 16. satırdaki çözümü buldum. Bu kod, belki de istemci tarafındaki doğrulayıcıları etkinleştirmek için formu ayrıştırıyor.
7.7. Bir ASP.NET uygulamasını İnternet üzerinden erişilebilir hale getirme
9.26 numaralı paragrafa bakınız.
7.8. Tek sayfalık bir uygulamadan Android için yerel bir uygulama oluşturma APU
9.27. paragrafa bakınız.

















































