Rappel client avec implémentation de la validation, exemple
Mise à jour : novembre 2007
Dans un rappel client, une fonction de script client envoie une demande à la page Web ASP.NET, qui exécute ensuite une version abrégée de son cycle de vie normal pour traiter le rappel. Pour garantir que les événements de rappel proviennent de l'interface utilisateur attendue, vous pouvez valider les rappels. Lors de la validation des rappels, vous enregistrez un événement pour validation pendant le rendu de la page Web, puis validez l'événement pendant le rappel.
Remarque : |
---|
La validation d'événement aide à sécuriser votre application Web contre les publications fausses, mais ne protège pas contre les attaques par relecture. Un schéma de validation de l'événement plus complet doit prendre en considération les caractéristiques de votre application Web et les autorisations de l'utilisateur qui accède à ses ressources. Pour plus d'informations, consultez Sécurité des applications Web ASP.NET. |
L'exemple abordé ici étend les Implémentation de rappel de client (C#), exemple et Implémentation de rappel de client (Visual Basic), exemple. Dans ces exemples, un contrôle ListBox nommé ListBox1 est un contrôle côté serveur qui affiche une liste de produits. Un élément <button> HTML (et non un contrôle serveur Button) exécute un rappel pour obtenir des informations sur l'inventaire du produit. L'exemple est étendu pour introduire des informations supplémentaires qui indiquent si un produit est en vente et autoriser l'affichage de ces informations pour les utilisateurs authentifiés uniquement. Un contrôle LoginView est utilisé avec le jeu de propriétés LoggedInTemplate pour afficher le contenu supplémentaire. Les utilisateurs anonymes de la page Web sont autorisés à exécuter un rappel pour obtenir des informations sur l'inventaire, alors que les utilisateurs connectés sont également autorisés à exécuter un rappel pour obtenir des informations sur les ventes. Le rappel pour les informations sur les ventes est enregistré pour la validation d'événement uniquement si l'utilisateur est authentifié. Cela empêche l'exécution du rappel par des utilisateurs qui ne sont pas authentifiés.
Exemple
Description
Dans l'exemple suivant, une page Web émule une recherche sur la base de données pour déterminer le nombre d'articles qui sont disponibles et si un article est en vente. Pour simplifier l'exemple, le magasin de données est représenté par deux listes de dictionnaires. Dans une application de production, on utiliserait plutôt une base de données. L'exemple illustre un scénario où la validation de rappels clients empêche un utilisateur anonyme d'exécuter un rappel qui est destiné uniquement aux utilisateurs authentifiés.
Code
<%@ Page Language="VB" AutoEventWireup="false"
CodeFile="ClientCallback.aspx.vb" Inherits="ClientCallback" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" >
<title>ASP.NET Example</title>
<script type="text/javascript">
function ReceiveServerData(rValue)
{
Results.innerText = rValue;
}
</script>
</head>
<body>
<form id="form1" >
<div>
<asp:ListBox id="ListBox1" ></asp:ListBox>
<br />
<br />
<button id="LookUpStockButton" onclick="LookUpStock()">Look Up Stock</button>
<asp:LoginView id="LoginView1" >
<LoggedInTemplate>
<button id="LookUpSaleButton" onclick="LookUpSale()">Look Up Back Order</button>
</LoggedInTemplate>
</asp:LoginView>
<br />
Item status: <span id="Results"></span>
</div>
</form>
</body>
</html>
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="ClientCallback.aspx.cs" Inherits="ClientCallback" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML
1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" >
<title>ASP.NET Example</title>
<script type="text/javascript">
function ReceiveServerData(rValue)
{
Results.innerText = rValue;
}
</script>
</head>
<body>
<form id="form1" >
<div>
<asp:ListBox id="ListBox1" ></asp:ListBox>
<br />
<br />
<button id="LookUpStockButton" onclick="LookUpStock()">Look Up Stock</button>
<asp:LoginView id="LoginView1" >
<LoggedInTemplate>
<button id="LookUpSaleButton" onclick="LookUpSale()">Look Up Back Order</button>
</LoggedInTemplate>
</asp:LoginView>
<br />
Item status: <span id="Results"></span>
</div>
</form>
</body>
</html>
Partial Class ClientCallback
Inherits System.Web.UI.Page
Implements System.Web.UI.ICallbackEventHandler
Protected catalog As ListDictionary
Protected saleitem As ListDictionary
Protected returnValue As String
Protected validationLookUpStock As String = "LookUpStock"
Protected validationLookUpSale As String = "LookUpSale"
Sub Page_Load(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles Me.Load
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), _
validationLookUpStock, "function LookUpStock() { " & _
"var lb = document.forms[0].ListBox1; " & _
"var product = lb.options[lb.selectedIndex].text; " & _
"CallServer(product, ""LookUpStock"");} ", True)
If (User.Identity.IsAuthenticated) Then
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), _
validationLookUpSale, "function LookUpSale() { " & _
"var lb = document.forms[0].ListBox1; " & _
"var product = lb.options[lb.selectedIndex].text; " & _
"CallServer(product, ""LookUpSale"");} ", True)
End If
Dim cbReference As String
cbReference = "var param = arg + '|' + context;" & _
Page.ClientScript.GetCallbackEventReference(Me, _
"param", "ReceiveServerData", "context")
Dim callbackScript As String = ""
callbackScript &= "function CallServer(arg, context) { " & _
cbReference & "} ;"
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), _
"CallServer", callbackScript, True)
' Populate List Dictionary with invented database data
catalog = New ListDictionary()
saleitem = New ListDictionary()
catalog.Add("monitor", 12)
catalog.Add("laptop", 10)
catalog.Add("keyboard", 23)
catalog.Add("mouse", 17)
saleitem.Add("monitor", 1)
saleitem.Add("laptop", 0)
saleitem.Add("keyboard", 0)
saleitem.Add("mouse", 1)
ListBox1.DataSource = catalog
ListBox1.DataTextField = "key"
ListBox1.DataBind()
End Sub
Public Sub RaiseCallbackEvent(ByVal eventArgument As String) _
Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
Dim argParts() As String = eventArgument.Split("|"c)
If ((argParts Is Nothing) OrElse (argParts.Length <> 2)) Then
returnValue = "A problem occurred trying to retrieve stock count."
Return
End If
Dim product As String = argParts(0)
Dim validationaction = argParts(1)
Select Case validationaction
Case "LookUpStock"
Try
Page.ClientScript.ValidateEvent("LookUpStockButton", validationaction)
If (catalog(product) Is Nothing) Then
returnValue = "Item not found."
Else
returnValue = catalog(product).ToString() & " in stock."
End If
Catch
returnValue = "Can not retrieve stock count."
End Try
Case "LookUpSale"
Try
Page.ClientScript.ValidateEvent("LookUpSaleButton", validationaction)
If (saleitem(product) Is Nothing) Then
returnValue = "Item not found."
Else
If (Convert.ToBoolean(saleitem(product))) Then
returnValue = "Item is on sale."
Else
returnValue = "Item is not on sale."
End If
End If
Catch
returnValue = "Can not retrieve sale status."
End Try
End Select
End Sub
Public Function GetCallbackResult() _
As String Implements _
System.Web.UI.ICallbackEventHandler.GetCallbackResult
Return returnValue
End Function
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Page.ClientScript.RegisterForEventValidation("LookUpStockButton", _
validationLookUpStock)
If (User.Identity.IsAuthenticated) Then
Page.ClientScript.RegisterForEventValidation("LookUpSaleButton", _
validationLookUpSale)
End If
MyBase.Render(writer)
End Sub
End Class
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class ClientCallback : System.Web.UI.Page,
System.Web.UI.ICallbackEventHandler
{
protected System.Collections.Specialized.ListDictionary catalog;
protected System.Collections.Specialized.ListDictionary saleitem;
protected String returnValue;
protected String validationLookUpStock = "LookUpStock";
protected String validationLookUpSale = "LookUpSale";
protected void Page_Load(object sender, EventArgs e)
{
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
validationLookUpStock, "function LookUpStock() { " +
"var lb = document.forms[0].ListBox1; " +
"var product = lb.options[lb.selectedIndex].text; " +
@"CallServer(product, ""LookUpStock"");} ", true);
if (User.Identity.IsAuthenticated)
{
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
validationLookUpSale, "function LookUpSale() { " +
"var lb = document.forms[0].ListBox1; " +
"var product = lb.options[lb.selectedIndex].text; " +
@"CallServer(product, ""LookUpSale"");} ", true);
}
String cbReference = "var param = arg + '|' + context;" +
Page.ClientScript.GetCallbackEventReference(this,
"param", "ReceiveServerData", "context");
String callbackScript;
callbackScript = "function CallServer(arg, context)" +
"{ " + cbReference + "} ;";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
"CallServer", callbackScript, true);
catalog = new System.Collections.Specialized.ListDictionary();
saleitem = new System.Collections.Specialized.ListDictionary();
catalog.Add("monitor", 12);
catalog.Add("laptop", 10);
catalog.Add("keyboard", 23);
catalog.Add("mouse", 17);
saleitem.Add("monitor", 1);
saleitem.Add("laptop", 0);
saleitem.Add("keyboard", 0);
saleitem.Add("mouse", 1);
ListBox1.DataSource = catalog;
ListBox1.DataTextField = "key";
ListBox1.DataBind();
}
public void RaiseCallbackEvent(String eventArgument)
{
string[] argParts = eventArgument.Split('|');
if ((argParts == null) || (argParts.Length != 2))
{
returnValue = "A problem occurred trying to retrieve stock count.";
return;
}
string product = argParts[0];
string validationaction = argParts[1];
switch (validationaction)
{
case "LookUpStock":
try
{
Page.ClientScript.ValidateEvent("LookUpStockButton", validationaction);
if (catalog[product] == null)
{
returnValue = "Item not found.";
}
else
{
returnValue = catalog[product].ToString() + " in stock.";
}
}
catch
{
returnValue = "Can not retrieve stock count.";
}
break;
case "LookUpSale":
try
{
Page.ClientScript.ValidateEvent("LookUpSaleButton", validationaction);
if (saleitem[product] == null)
{
returnValue = "Item not found.";
}
else
{
if (Convert.ToBoolean(saleitem[product]))
returnValue = "Item is on sale.";
else
returnValue = "Item is not on sale.";
}
}
catch
{
returnValue = "Can not retrieve sale status.";
}
break;
}
}
public String GetCallbackResult()
{
return returnValue;
}
protected override void Render(HtmlTextWriter writer)
{
Page.ClientScript.RegisterForEventValidation("LookUpStockButton",
validationLookUpStock);
if (User.Identity.IsAuthenticated)
{
Page.ClientScript.RegisterForEventValidation("LookUpSaleButton",
validationLookUpSale);
}
base.Render(writer);
}
}
Commentaires
La page Web émule une consultation de base de données afin de déterminer le nombre d'articles disponibles, ou en réserve, pour une série de produits (écrans, claviers, etc.). Pour simplifier cet exemple de code, la base de données est représentée par une liste de dictionnaire qui contient un petit jeu d'articles. La clé de chacun des articles de la table est le nom de l'article (par exemple, écran), et sa valeur est le nombre d'articles en réserve. Dans une application de production, on utiliserait plutôt une base de données.
Lorsque la page s'exécute, un contrôle ListBox est lié à la table de hachage afin que le contrôle ListBox affiche la liste des produits. Pour les utilisateurs authentifiés, la page est rendue avec deux éléments <button> HTML dont les événements onclick sont liés à une fonction cliente nommée LookUpStock et une fonction cliente nommée LookUpSale, respectivement. Pour les utilisateurs anonymes, la page est rendue avec un seul élément <button> HTML dont l'événement onclick est lié à LookUpStock. Un contrôle LoginView est utilisé pour spécifier les boutons qui sont affichés. Dans un événement Render substitué pour la page, les boutons sont enregistrés pour la validation. Si l'utilisateur n'est pas authentifié, le bouton qui initialise le rappel pour LookUpSale n'est pas enregistré et la tentative de rappel échouera.
La page code-behind ajoute à la page le script côté client via la méthode RegisterClientScriptBlock. Le script ajouté à la page comprend une fonction nommée CallServer, laquelle obtient le nom de la méthode qui publiera sur le serveur à partir de la méthode GetCallbackEventReference.
Le rappel client appelle la méthode RaiseCallbackEvent pour déterminer la réserve disponible du produit qui lui a été passé. La méthode GetCallbackResult retourne la valeur. Notez que les arguments échangés entre le script client et le code serveur ne peuvent être que des chaînes. Pour passer ou recevoir plusieurs valeurs, vous pouvez concaténer des valeurs respectivement dans la chaîne d'entrée ou de retour.
Note de sécurité : |
---|
Si votre page Web et les rappels clients gèrent l'affichage de données sensibles ou d'opérations d'insertion, de mise à jour ou de suppression des données, il est recommandé de valider les rappels pour vous assurer que l'élément d'interface utilisateur prévu exécute le rappel. |
Voir aussi
Tâches
Comment : implémenter des rappels dans des pages Web ASP.NET
Concepts
Implémentation de rappel de client (C#), exemple
Implémentation de rappel de client (Visual Basic), exemple