Exportieren (0) Drucken
Alle erweitern

Clientrückruf und Beispiel für die Implementierung einer Validierung

Bei einem Clientrückruf sendet eine Clientskriptfunktion eine Anforderung an die ASP.NET-Webseite. Diese führt dann eine Kurzversion des normalen Lebenszyklus aus, um den Rückruf zu bearbeiten. Um sicherzustellen, dass Rückrufereignisse von der erwarteten Benutzeroberfläche stammen, können Sie Rückrufe überprüfen. Bei einer Rückrufvalidierung wird ein Ereignis während der Wiedergabe der Webseite für die Validierung registriert und dann während des Rückrufs validiert.

NoteHinweis

Mit der Ereignisvalidierung können Webanwendungen vor falschen Postbacks, jedoch nicht vor wiederholten Angriffen geschützt werden. Ein etwas umfassenderes Ereignisvalidierungsschema sollte auch die Besonderheiten der Webanwendung und die Berechtigungen der Benutzer berücksichtigen, die auf die Ressourcen zurückgreifen. Weitere Informationen finden Sie unter Sicherheit für ASP.NET-Webanwendungen.

Im hier erläuterten Beispiel werden Beispielimplementierung eines Clientrückrufs (C#) und Beispiel für das Implementieren von Clientrückrufen (Visual Basic) erweitert. In diesen Beispielen handelt es sich bei dem ListBox-Steuerelement ListBox1 um ein Steuerelement des Servers, mit dem eine Produktliste angezeigt wird. Ein HTML <button>-Element (nicht ein Button-Serversteuerelement) führt einen Rückruf aus, um Produktbestandsdaten abzurufen. Das Beispiel wird so erweitert, dass zusätzliche Informationen zum Verkaufstatus eines Produkts bereitgestellt werden und diese Informationen nur von authentifizierten Benutzern angezeigt werden dürfen. Ein LoginView-Steuerelement wird verwendet, bei dem die LoggedInTemplate-Eigenschaft auf die Anzeige weiterer Inhalte festgelegt ist. Anonyme Benutzer der Webseite können einen Rückruf ausführen, um Bestandsdaten abzurufen. Angemeldete Benutzer dagegen können über einen Rückruf auch Verkaufsinformationen abrufen. Der Rückruf für die Verkaufsinformationen wird nur dann für die Ereignisvalidierung registriert, wenn der Benutzer authentifiziert ist. So wird verhindert, dass nicht authentifizierte Benutzer einen Rückruf ausführen können.

Beispiel

Im folgenden Beispiel emuliert eine Webseite eine Datenbanksuche, um die Anzahl der verfügbaren Artikel sowie die Verfügbarkeit eines Artikels zu ermitteln. Um das Beispiel zu vereinfachen, wird der Datenspeicher durch zwei Wörterbuchlisten dargestellt. In einer Betriebsanwendung würde stattdessen eine Datenbank verwendet werden. In diesem Beispiel wird ein Szenario dargestellt, bei dem durch Überprüfen von Clientrückrufen verhindert wird, dass ein anonymer Benutzer einen Rückruf ausführt, der nur für authentifizierte Benutzer vorgesehen ist.

<%@ 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" runat="server">
    <title>ASP.NET Example</title>
<script type="text/javascript">    
    function ReceiveServerData(rValue)
    {
        Results.innerText = rValue;
    }
  </script>
</head>
<body>
  <form id="form1" runat="server">
    <div>
      <asp:ListBox id="ListBox1" runat="server"></asp:ListBox>
      <br />
      <br />
      <button id="LookUpStockButton" onclick="LookUpStock()">Look Up Stock</button>
      <asp:LoginView id="LoginView1" runat="server">
      <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>

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);
    }
}

Die Webseite emuliert eine Datenbanksuche, um für einige Produkte (Monitore, Tastaturen usw.) die Anzahl der verfügbaren oder vorrätigen Artikel zu bestimmen. Um das Codebeispiel zu vereinfachen, wird die Datenbank als Wörterbuchliste dargestellt, die nur einige wenige Elemente enthält. Für jeden Artikel in der Tabelle ist der Artikelname der Schlüssel (z. B. Monitor), und der Wert beschreibt die Anzahl der vorrätigen Artikel. In einer Betriebsanwendung würde stattdessen eine Datenbank verwendet werden.

Beim Ausführen der Seite wird ein ListBox-Steuerelement an die Hashtabelle gebunden, damit das ListBox-Steuerelement die Produktliste anzeigen kann. Für authentifizierte Benutzer wird die Seite mit zwei HTML <button>-Elementen gerendert, deren onclick-Ereignisse an eine Clientfunktion mit dem Namen LookUpStock bzw. an eine Clientfunktion mit dem Namen LookUpSale gebunden sind. Für anonyme Benutzer wird die Seite mit nur einem HTML <button>-Element gerendert, dessen onclick-Ereignis an LookUpStock gebunden ist. Ein LoginView-Steuerelement wird verwendet, um anzugeben, welche Schaltflächen angezeigt werden. In einem überschriebenen Render-Ereignis für die Seite werden die Schaltflächen für die Validierung registriert. Wenn der Benutzer nicht authentifiziert ist, wird die Schaltfläche, die den Rückruf für LookUpSale auslöst, nicht registriert und ein Rückrufversuch schlägt fehl.

Die Code-Behind-Seite fügt der Seite über die RegisterClientScriptBlock-Methode Clientskripts hinzu. Das hinzugefügte Skript enthält die CallServer-Funktion, die von der GetCallbackEventReference-Methode den Namen der Methode abruft, die das Postback an den Server ausführt.

Der Clientrückruf ruft die RaiseCallbackEvent-Methode auf, die den verfügbaren Bestand für den an sie übergebenen Artikel ermittelt. Die GetCallbackResult-Methode gibt den Wert zurück. Beachten Sie, dass es sich bei den Argumenten, die zwischen Clientskript und Servercode hin und her gesendet werden, nur um Zeichenfolgen handeln darf. Sie können mehrere Werte gleichzeitig eingeben oder empfangen, wenn Sie in der Eingabezeichenfolge bzw. in der Ausgabezeichenfolge jeweils Werte verknüpfen.

Security noteSicherheitshinweis Hinweis

Wenn die Webseite und die Clientrückrufe vertrauliche Daten anzeigen oder mit Operationen arbeiten, die Daten einfügen, aktualisieren oder löschen, sollten Sie die Rückrufe unbedingt überprüfen, um sicherzustellen, dass das dafür vorgesehene Element der Benutzeroberfläche den Rückruf ausführt.

Siehe auch

Anzeigen:
© 2015 Microsoft