A la sauce ASP.NET classique
Dans le cadre d’une application ASP.NET, on aurait construit une page qui contiendrait un Textbox et un bouton associé à un handler sur le click.
Et pour faire joli, on aurait rajouté une image pour dire que le pseudo est libre, et une autre image pour dire que le pseudo est déjà pris.
Ce qui donne une page de ce genre :
Page.aspx
<asp:Label Text= »Entrer le pseudo » runat= »server » />
<asp:TextBox runat= »server » ID= »Login » />
<asp:Button Text= »Vérifier » OnClick= »VerifPseudo » runat= »server » />
<asp:Image ID= »OkImg » runat= »server » ImageUrl= »~/Images/ok.png » Visible= »false » /> <asp:Image ID= »ErrImg » runat= »server » ImageUrl= »~/Images/err.png » Visible= »false » />
Le code behind associé sera :
Page.aspx.cs
protected void VerifPseudo(object sender, EventArgs e)
{
if (UserService.PseudoLibre(Login.Text))
{
OkImg.Visible = true;
ErrImg.Visible = false;
}
else
{
OkImg.Visible = false;
ErrImg.Visible = true;
}
}
Rien de bien compliqué. Ce qui nous donne :
Nous allons nous attacher désormais à rendre notre superbe page un peu plus AJAX friendly…
Note : dans toutes les pages que nous allons découvrir et créer, on rajoutera un contrôle Label témoin indiquant l’heure courante au chargement de la page.
Ceci nous permettra de montrer qu’on a bien eu un rendu partiel et que la page ne s’est pas rechargée totalement.
Le code behind correspondant dans chaque page sera :
Page.aspx.cs
protected override void OnInit(EventArgs e)
{
LabelTemoin.Text = DateTime.Now.ToLongTimeString();
base.OnInit(e);
}
Je n’en parlerai plus désormais et ferais comme si il était inclus dans chaque page.
Utilisation d’AJAX
Rendu partiel en utilisant le contrôle UpdatePanel
On utilise le contrôle UpdatePanel et son inséparable ScriptManager qui vont nous permettre de générer le code client javascript pour gérer le rendu partiel.
Pour ce faire, pas besoin d’énormes transformations de la page. On rajoute un contrôle ScriptManager et on encapsule le reste dans un UpdatePanel :
PageUpdatePanel.aspx
<asp:ScriptManager runat= »server » ID= »ScriptManager » /> <asp:Label runat= »server » ID= »LabelTemoin » />
<asp:UpdatePanel runat= »server » ID= »UpdatePanel1″ UpdateMode= »Conditional »> <ContentTemplate>
<asp:Label ID= »Label1″ Text= »Entrer le pseudo » runat= »server » /> <asp:TextBox runat= »server » ID= »Login » />
<asp:Button ID= »Button1″ Text= »Vérifier » OnClick= »VerifPseudo » runat= »server » /> <asp:Image ID= »OkImg » runat= »server » ImageUrl= »~/Images/ok.png » Visible= »false » /> <asp:Image ID= »ErrImg » runat= »server » ImageUrl= »~/Images/err.png » Visible= »false » /> </ContentTemplate>
</asp:UpdatePanel>
Le code behind permettant de vérifier que le pseudo est libre ne change pas, à savoir :
PageUpdatePanel.aspx.cs
protected void VerifPseudo(object sender, EventArgs e)
{
if (UserService.PseudoLibre(Login.Text))
{
OkImg.Visible = true;
ErrImg.Visible = false;
}
else
{
OkImg.Visible = false;
ErrImg.Visible = true;
PageUpdatePanel.aspx.cs
}
Et voilà, nous avons un beau rendu partiel. Nous sommes capables d’indiquer si un pseudo est libre sans avoir à recharger toute la page.
Un des avantages visible directement est qu’on a pu faire un rendu partiel sans écrire une seule ligne de javascript, tout est pris en charge par ASP.NET.
Rendu partiel en utilisant l’objet XMLHttpRequest, l’AJAX de la vieille école
L’objet XMLHttpRequest va nous permettre de faire un appel asynchrone (coté client) à une page (coté serveur) et de récupérer le retour de cette page.
A cet effet, toujours dans l’optique de vérifier si un pseudo est libre, on peut envisager d’appeler une page ASPX avec le pseudo en paramètre. Cette page va vérifier si le pseudo est libre, et nous renvoyer l’image correspondante.
Il nous restera plus qu’à afficher cette image coté client.
Créons une page CheckPseudo.aspx.
On va nettoyer son contenu pour ne garder que :
CheckPseudo.aspx
<%@ Page Language= »C# » AutoEventWireup= »false » CodeBehind= »CheckPseudo.aspx.cs » Inherits= »CompareAjaxMethods.Page <form id= »form1″ runat= »server »>
<asp:Image runat= »server » id= »OkImg » Src= »~Images/ok.png » /> <asp:Image runat= »server » id= »ErrImg » Src= »~Images/ok.png » />
</form>
J’ai décidé arbitrairement que la page serait appelée en POST, mais on peut également envisager de faire cet appel en GET. Voici le code behind de la page CheckPseudo.aspx :
CheckPseudo.aspx.cs
protected override void OnLoad(System.EventArgs e)
{
string pseudo = Request.Form[« pseudo »];
if (UserService.PseudoLibre(pseudo))
{
OkImg.Visible = true;
ErrImg.Visible = false;
}
else
{
OkImg.Visible = false;
ErrImg.Visible = true;
}
base.OnLoad(e);
}
Dans le OnLoad de la page CheckPseudo.aspx, on récupère la valeur du paramètre « pseudo » passé en POST et on affiche l’image en fonction du retour de l’appel au service de vérification de pseudo.
Ce qui fait que la page de démonstration (PageXMLHttpRequestPage.aspx) n’aura pas besoin de contenir d’images,
vu que c’est la réponse à CheckPseudo qui va nous les renvoyer. Par contre, elle aura besoin d’un container pour
afficher cette réponse : par exemple un div « result ».
Ce qui nous donne :
PageXMLHttpRequestPage.aspx
<form id= »form1″ runat= »server »>
<asp:Label runat= »server » ID= »LabelTemoin » /><br />
PageXMLHttpRequestPage.aspx
<asp:Label ID= »Label1″ Text= »Entrer le pseudo » runat= »server » /> <asp:TextBox runat= »server » ID= »Login » />
<input type= »button » onclick= »VerifPseudoJs(‘<%=Login.ClientID %>’) » value= »Vérifier » />
<div id= »result »></div>
</form>
Notez qu’on passe en paramètre à la fonction VerifPseudoJs l’ID client du TextBox Login.
On inclura dans cette page deux fichiers javascript :
PageXMLHttpRequestPage.aspx
<script type= »text/javascript » src= »/js/Helper.js »></script> <script type= »text/javascript » src= »/js/XmlHttpPage.js »></script>
Le premier contient des méthodes Helper, à savoir la récupération de l’objet XMLHttpRequest et une méthode pour changer le display d’une balise :
Helper.js
function getXhr()
{
var xhr = null;
if (window.XMLHttpRequest) // Firefox et autres
xhr = new XMLHttpRequest();
else if (window.ActiveXObject)
{ // Internet Explorer try
{
xhr = new ActiveXObject(« Msxml2.XMLHTTP »);
} catch (e)
{
xhr = new ActiveXObject(« Microsoft.XMLHTTP »);
}
}
else
{ // XMLHttpRequest non supporté par le navigateur
alert(« Votre navigateur ne supporte pas les objets XMLHTTPRequest… »); xhr = false;
}
return xhr
}
function setDisplay(id, visible)
{
var o;
if (document.getElementById)
o = document.getElementById(id).style;
else if (document.layers)
o = document.layers[id];
else if (document.all)
o = document.all[id].style;
if (o)
o.display = (visible ? ‘block’ : ‘none’);
}
Il restera à faire l’appel à la méthode VerifPseudoJs qui sera contenu dans le fichier XmlHttpPage.js :
XmlHttpPage.js
function VerifPseudoJs(idText)
{
var xhr = getXhr();
XmlHttpPage.js
if (xhr)
{
xhr.onreadystatechange = function()
{
// On ne fait quelque chose que si on a tout reçu et que le serveur est ok if (xhr.readyState == 4 && xhr.status == 200)
{
document.getElementById(‘result’).innerHTML = xhr.responseText;
}
}
xhr.open(« POST », « CheckPseudo.aspx », true);
xhr.setRequestHeader(« Content-type », « application/x-www-form-urlencoded »); var data = « pseudo= » + document.getElementById(idText).value; xhr.send(data);
}
}
Il s’agit de récupérer l’objet XMLHTTPRequest et d’appeler la page CheckPseudo.aspx en POST, en lui passant le paramètre pseudo et le contenu du textbox.
Ensuite, une callback sera appelée une fois que la requete AJAX sera terminée. C’est à ce moment là qu’on remplira le div « result » avec le contenu de la réponse (utilisation de innerHTML). Il est à noter que le contenu retourné, dans notre cas, est :
Réponse de CheckPseudo.aspx
<div>
<input type= »hidden » name= »__VIEWSTATE » id= »__VIEWSTATE »
value= »/wEPDwULLTExNzU3MzQyMTAPZBYCZg9kFgICAQ8PFgIeB1Zpc2libGVoZGRkX49ztZNge2YjgU7qgcf5ZKkqG3E
= » />
</div>
<img id= »ErrImg » src= »/Images/err.png » src= » » style= »border-width:0px; » />
et contient notamment le viewstate.
On peut constater qu’on n’a pas eu besoin d’écrire de code behind dans notre page. Par contre, il y en a dans la page CheckPseudo.aspx.
Notons également la présence du viewstate, qui dans ce cas n’est pas énorme, mais qui peut potentiellement l’être, par exemple si la page contient une grille…
L’obligation d’écrire une page pour traiter l’existence du pseudo est une contrainte non négligeable et qui peut devenir difficile à maintenir si on en augmente le nombre et la complexité.
Rendu partiel avec XMLHttpRequest et IHttpHandler
Pourquoi appeler la page CheckPseudo.aspx ?
On peut se dire que le but est de faire un appel de service et que ce n’est pas si logique que ca de devoir passer par une page ASPX pour y arriver. Une page est un système complexe, gérant son état (ViewState), passant par plusieurs étapes lors de son cycle de vie, générant un rendu, etc … Pourquoi toute cette mécanique pour juste avoir à afficher une réponse ?
Effectivement, cette question a toute sa justification. De plus, ASP.NET nous fournit un mécanisme qui permet de nous en passer des pages dans ce cas : les handler.
Un handler est une classe qui doit implémenter IHttpHandler.
Cette classe doit également être déclarée dans le web.config avec un verbe associé.
Créons donc la classe CheckPseudoHandler.cs
CheckPseudoHandler.cs
public class CheckPseudoHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
CheckPseudoHandler.cs
{
context.Response.Cache.SetCacheability(HttpCacheability.NoCache); context.Response.ContentType = « text/plain »;
string pseudo = context.Request.Form[« pseudo »];
if (UserService.PseudoLibre(pseudo))
context.Response.Write(true);
else
context.Response.Write(false);
}
public bool IsReusable
{
get { return false; }
}
}
Cette classe va faire grosso modo la même chose que la page CheckPseudo.aspx. C’est à dire lire le pseudo passé en paramètre en POST, appeler le service de vérification de pseudo et écrire la réponse.
La réponse ici en l’occurrence sera du « text/plain » et contiendra « True » ou « False » en fonction du résultat de l’appel au service.
Pour qu’ASP.NET puisse associer une requête à ce handler, il faudra le déclarer dans le web.config, à la section :
web.config
<system.web>
<httpHandlers>
<add verb= »POST » path= »ExistPseudo »
type= »CompareAjaxMethods.CheckPseudoHandler, CompareAjaxMethods » />
</httpHandlers>
</system.web>
On indique ici qu’ASP.NET doit répondre aux requêtes POST de type « ExistPseudo » en utilisant le gestionnaire HTTP
présent dans la classe CheckPseudoHandler.
La page sera donc :
PageXMLHttpRequestHandler.aspx
<form id= »form1″ runat= »server »>
<asp:Label runat= »server » ID= »LabelTemoin » /><br />
<asp:Label ID= »Label1″ Text= »Entrer le pseudo » runat= »server » /> <asp:TextBox runat= »server » ID= »Login » />
<input type= »button » onclick= »VerifPseudoJs(‘<%=Login.ClientID %>’) » value= »Vérifier » />
<div id= »result »></div>
</form>
On aura deux scripts à inclure :
PageXMLHttpRequestHandler.aspx
<script type= »text/javascript » src= »/js/Helper.js »></script> <script type= »text/javascript » src= »/js/XmlHttpPage.js »></script>
XmlHttpPage.js contiendra quasiment la même fonction que dans le chapitre précédent, seuls l’appel et le traitement de la réponse AJAX changent:
XmlHttpPage.js
function VerifPseudoJs(idText, idOk, idErr)
{
XmlHttpPage.js
var xhr = getXhr();
if (xhr)
{
xhr.onreadystatechange = function()
{
// On ne fait quelque chose que si on a tout reçu et que le serveur est ok if (xhr.readyState == 4 && xhr.status == 200)
{
if (xhr.responseText == ‘True’)
{
setDisplay(idOk, true); setDisplay(idErr, false);
}
else
{
setDisplay(idOk, false); setDisplay(idErr, true);
}
}
}
xhr.open(« POST », « ExistPseudo », true);
xhr.setRequestHeader(« Content-type », « application/x-www-form-urlencoded »); var data = « pseudo= » + document.getElementById(idText).value; xhr.send(data);
}
}
On constate que l’appel de page se transforme en un appel à ExistPseudo.
Désormais, on compare la réponse à « True », simplement. On affichera les images en fonction de cette comparaison. Pas de code behind ici non plus, par contre, il faudra écrire un handler de page. Ce qui peut être une charge non négligeable si on en a beaucoup à écrire.
1.Introduction
2.Le fil rouge
2.A la sauce ASP.NET classique
3.Utilisation d’AJAX
3.1.Rendu partiel en utilisant le contrôle UpdatePanel
3.2.Rendu partiel en utilisant l’objet XMLHttpRequest, l’AJAX de la vieille école
3.3.Rendu partiel avec XMLHttpRequest et IHttpHandler
3.4.Rendu partiel en utilisant les PageMethods
3.5.Rendu partiel en utilisant un web service WCF
4.Utilisation de l’AJAX avec jQuery
4.1.Appel à la page CheckPseudo.aspx
4.2.Appel au handler de page
4.3.Utilisation d’un handler de page renvoyant du JSON
4.4.Utilisation de jQuery avec un Web Service JSON
5.Considérations sur les appels AJAX
5.1.Méthode avec l’UpdatePanel
5.2.Méthode avec XMLHttpRequest et appel de CheckPseudo.aspx
5.3.Méthode avec XMLHttpRequest et appel du handler
5.4.Avec les PageMethods
5.5.Avec un Web Service WCF
5.6.Avec jQuery et CheckPseudo.aspx
5.7.Avec jQuery et un handler de page
5.8.Avec jQuery et le handler de page JSON
5.9.Avec jQuery et un web service WCF
5.10.Totaux
6.Téléchargement
7.Conclusion