Condividi tramite


Utilizzo del controllo UpdatePanel con un servizio Web

Aggiornamento: novembre 2007

Il controllo UpdatePanel semplifica il rendering a pagina parziale nelle pagine Web ASP.NET poiché la funzionalità AJAX di ASP.NET gestisce automaticamente le richieste di postback asincrone e gli aggiornamenti. La funzionalità AJAX consente inoltre di chiamare i servizi Web ASP.NET utilizzando ECMAScript (JavaScript) nel browser. Uno dei vantaggi offerti dalla chiamata di un servizio Web utilizzando uno script client deriva dal fatto che l'attesa della risposta da una richiesta del servizio Web non blocca il browser. Gli utenti possono continuare a lavorare senza attendere che il servizio Web completi l'elaborazione della richiesta.

In questa esercitazione viene illustrato come utilizzare un servizio Web mediante un controllo UpdatePanel. Una funzione JavaScript chiama il servizio Web per recuperare i dati e popolare gli elementi DOM all'interno di un controllo UpdatePanel con i dati restituiti dal servizio Web. Il codice server mantiene i dati recuperati dal servizio Web tra postback asincroni.

In questo argomento si presuppone la conoscenza del controllo UpdatePanel e dei servizi Web. In caso contrario, consultare i seguenti argomenti:

Prerequisiti

Per implementare le procedure nell'ambiente di sviluppo in uso è necessario:

  • Microsoft Visual Studio 2005 o Visual Web Developer Express Edition.

  • Sito Web ASP.NET con supporto AJAX.

  • Accesso al database Northwind e una stringa di connessione denominata NorthwindConnectionString definita nel file Web.config. Per ulteriori informazioni su come creare una stringa di connessione, vedere Procedura: leggere stringhe di connessione dal file Web.config.

Creazione di un servizio Web

Per iniziare verrà creato un servizio Web che sia possibile chiamare.

Per creare un servizio Web per restituire quantità di prodotto

  1. In un sito Web ASP.NET con supporto AJAX creare un nuovo file del servizio Web denominato ProductQueryService.asmx.

    Per ulteriori informazioni sulla creazione di un servizio Web, vedere Chiamata a servizi Web da script client.

  2. Nel codice del servizio Web importare gli spazi dei nomi N:System.Data, N:System.Data.SqlClient, System.Configuration e N:System.Web.Script.Services.

    Imports System.Data
    Imports System.Data.SqlClient
    Imports System.Configuration
    Imports System.Web.Script.Services
    
    using System.Web.Script.Services;
    using System.Data;
    using System.Data.SqlClient;
    using System.Configuration;
    

    Nel metodo del servizio Web che verrà creato, verranno utilizzati i tipi di questi spazi dei nomi.

  3. Inserire la classe ProductQueryService in un spazio dei nomi denominato Samples.

  4. Aggiungere l'attributo ScriptServiceAttribute alla classe.

    Questo attributo consente al servizio Web di essere richiamato da uno script client.

  5. Sostituire il metodo HelloWorld predefinito con il metodo GetProductQuantity seguente:

    <WebMethod()> _
    Public Function GetProductQuantity(ByVal productID As String) As String
        Dim cn As SqlConnection = _
            New SqlConnection(ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString)
        Dim cmd As SqlCommand = _
            New SqlCommand("SELECT [UnitsInStock] FROM [Alphabetical list of products] WHERE ([ProductID] = @ProductID)", cn)
        cmd.Parameters.AddWithValue("productID", productID)
        Dim unitsInStock As String = ""
        cn.Open()
        Using dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
            Do While dr.Read()
                unitsInStock = dr(0).ToString()
            Loop
    
        End Using
        System.Threading.Thread.Sleep(3000)
        Return unitsInStock
    End Function
    
    [WebMethod]
    public string GetProductQuantity(string productID)
    {
        SqlConnection cn =
            new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString);
        SqlCommand cmd = new SqlCommand(
            "SELECT [UnitsInStock] FROM [Alphabetical list of products] WHERE ([ProductID] = @ProductID)", cn);
        cmd.Parameters.Add("productID", productID);
        String unitsInStock = "";
        cn.Open();
        using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
        {
            while (dr.Read())
                unitsInStock = dr[0].ToString();
        }
        System.Threading.Thread.Sleep(3000);
        return unitsInStock;
    }
    

    Mediante il codice vengono effettuate le seguenti operazioni:

    • Viene creato un nuovo oggetto SqlConnection che utilizza una stringa di connessione denominata NorthwindConnectionString.

    • Viene creato un nuovo oggetto SqlCommand che contiene un comando SQL per recuperare il numero di unità in magazzino per un ID del prodotto specificato.

    • Il valore restituito viene impostato su una stringa utilizzata come risposta inviata al browser.

      Nota:

      Per questa esercitazione il metodo Web introduce un ritardo artificiale. In pratica, non si introduce un ritardo. Il ritardo invece è il risultato del traffico del server o del servizio Web che richiede lunghi tempi di elaborazione, ad esempio una query di database di lunga durata.

  6. Salvare le modifiche, quindi premere CTRL+F5 per visualizzare la pagina in un browser.

  7. Fare clic sul collegamento GetProductQuantity per richiamare il metodo Web.

  8. Immettere 6 nella casella productID, quindi fare clic su Richiama.

    La quantità del prodotto viene restituita come XML nel browser dimostrando che il servizio Web funziona come previsto.

    <%@ WebService Language="VB" Class="Samples.ProductQueryService" %>
    
    Imports System
    Imports System.Web
    Imports System.Web.Services
    Imports System.Web.Services.Protocols
    Imports System.Data
    Imports System.Data.SqlClient
    Imports System.Configuration
    Imports System.Web.Script.Services
    Namespace Samples
    
        <ScriptService()> _
        <WebService(Namespace:="http://tempuri.org/")> _
        <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
        Public Class ProductQueryService
            Inherits System.Web.Services.WebService
    
            <WebMethod()> _
            Public Function GetProductQuantity(ByVal productID As String) As String
                Dim cn As SqlConnection = _
                    New SqlConnection(ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString)
                Dim cmd As SqlCommand = _
                    New SqlCommand("SELECT [UnitsInStock] FROM [Alphabetical list of products] WHERE ([ProductID] = @ProductID)", cn)
                cmd.Parameters.AddWithValue("productID", productID)
                Dim unitsInStock As String = ""
                cn.Open()
                Using dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
                    Do While dr.Read()
                        unitsInStock = dr(0).ToString()
                    Loop
    
                End Using
                System.Threading.Thread.Sleep(3000)
                Return unitsInStock
            End Function
        End Class
    End Namespace
    
    <%@ WebService Language="C#" Class="Samples.ProductQueryService" %>
    
    using System;
    using System.Web;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.Web.Script.Services;
    using System.Data;
    using System.Data.SqlClient;
    using System.Configuration;
    namespace Samples
    {
        [ScriptService]
        [WebService(Namespace = "http://tempuri.org/")]
        [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
        public class ProductQueryService : System.Web.Services.WebService
        {
    
            [WebMethod]
            public string GetProductQuantity(string productID)
            {
                SqlConnection cn =
                    new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString);
                SqlCommand cmd = new SqlCommand(
                    "SELECT [UnitsInStock] FROM [Alphabetical list of products] WHERE ([ProductID] = @ProductID)", cn);
                cmd.Parameters.Add("productID", productID);
                String unitsInStock = "";
                cn.Open();
                using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                {
                    while (dr.Read())
                        unitsInStock = dr[0].ToString();
                }
                System.Threading.Thread.Sleep(3000);
                return unitsInStock;
            }
        }
    }
    

Creazione di codice JavaScript per chiamare il servizio Web

In questa procedura verrà creato un file JavaScript che chiama il servizio Web creato nella procedura precedente.

Per creare un file JavaScript per utilizzare il servizio Web

  1. Creare un nuovo file JScript denominato ProductQueryScript.js.

  2. Aggiungere al file il seguente script:

    function GetQuantity(productID, elemToUpdate, productLabelElem, buttonElem) {
       var userContext = [productID, elemToUpdate, productLabelElem, buttonElem];
       Samples.ProductQueryService.GetProductQuantity(productID, OnSucceeded, null, userContext, null);
       $get(buttonElem).value = "Retrieving value...";
    }
    function OnSucceeded(result, userContext) {
       var productID = userContext[0];
       var elemToUpdate = userContext[1];
       var productLabelElem = userContext[2];
       var buttonElem = userContext[3];
       $get(buttonElem).value = "Get Quantity from Web Service";
       if ($get(elemToUpdate) !== null && $get(productLabelElem).innerHTML == productID) {
         $get(elemToUpdate).value = result;
       }
    }
    
    function GetQuantity(productID, elemToUpdate, productLabelElem, buttonElem) {
       var userContext = [productID, elemToUpdate, productLabelElem, buttonElem];
       Samples.ProductQueryService.GetProductQuantity(productID, OnSucceeded, null, userContext, null);
       $get(buttonElem).value = "Retrieving value...";
    }
    function OnSucceeded(result, userContext) {
       var productID = userContext[0];
       var elemToUpdate = userContext[1];
       var productLabelElem = userContext[2];
       var buttonElem = userContext[3];
       $get(buttonElem).value = "Get Quantity from Web Service";
       if ($get(elemToUpdate) !== null && $get(productLabelElem).innerHTML == productID) {
         $get(elemToUpdate).value = result;
       }
    }
    

    Lo script esegue le seguenti attività:

    • Crea una funzione denominata GetQuantity che richiama il metodo del servizio Web GetProductQuantity.

    • Crea una funzione denominata OnSucceeded richiamata quando la chiamata del servizio Web restituisce un risultato.

Creazione di una pagina Web per la visualizzazione dei dati

Verrà ora creata una pagina Web contenente un controllo UpdatePanel. I controlli all'interno del controllo UpdatePanel consentono di visualizzare le informazioni dal database Northwind.

Per creare una pagina Web per visualizzare i prodotti

  1. Creare una nuova pagina Web e passare alla visualizzazione Progettazione.

  2. Nella scheda Estensioni AJAX della casella degli strumenti, fare doppio clic sul controllo ScriptManager per aggiungerlo alla pagina.

  3. Fare doppio clic sul controllo UpdatePanel nella casella degli strumenti per aggiungere un controllo UpdatePanel alla pagina.

  4. Fare clic all'interno del controllo UpdatePanel, quindi nella scheda Dati della casella degli strumenti fare doppio clic sul controllo DataList.

  5. Nel pannello Attività DataList selezionare <Nuova origine dati...> dall'elenco Scegli origine dati.

    Nota:

    Se il pannello Attività DataList non viene visualizzato, fare clic con il pulsante destro del mouse sul controllo DataList e selezionare Mostra smart tag.

    Verrà visualizzata la Configurazione guidata origine dati.

  6. Selezionare Database, accettare il nome predefinito SqlDataSource1, quindi fare clic su OK.

  7. Nell'elenco Specificare la connessione dati che deve essere utilizzata dall'applicazione per connettersi al database selezionare NorthwindConnectionString, quindi scegliere Avanti.

  8. In Specificare la modalità di recupero dei dati dal database selezionare Specificare le colonne di una tabella o visualizzazione, selezionare Products dall'elenco e nell'elenco Colonne selezionare ProductID e ProductName.

  9. Fare clic sul pulsante WHERE.

    Viene visualizzata la finestra di dialogo Aggiungi clausola WHERE.

  10. Nell'elenco Colonne selezionare CategoryID e nell'elenco Origine selezionare Nessuna.

  11. Nella sezione Proprietà parametro della finestra di dialogo immettere 1 nella casella di testo Valore.

  12. Fare clic su Aggiungi per aggiungere la clausola WHERE all'istruzione SELECT.

  13. Scegliere OK per chiudere la finestra di dialogo Aggiungi clausola WHERE.

  14. Fare clic su Avanti, quindi su Fine per chiudere la procedura guidata.

  15. Passare alla visualizzazione Origine e verificare che il controllo SqlDataSource sia simile a quello riportato nell'esempio seguente:

    <asp:SqlDataSource ID="SqlDataSource1"  ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
        SelectCommand="SELECT [ProductName], [ProductID] FROM [Alphabetical list of products] WHERE ([CategoryID] = @CategoryID)">
        <SelectParameters>
            <asp:Parameter DefaultValue="1" Name="CategoryID" Type="Int32" />
        </SelectParameters>
    </asp:SqlDataSource>
    
    <asp:SqlDataSource ID="SqlDataSource1"  ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
        SelectCommand="SELECT [ProductName], [ProductID] FROM [Alphabetical list of products] WHERE ([CategoryID] = @CategoryID)">
        <SelectParameters>
            <asp:Parameter DefaultValue="1" Name="CategoryID" Type="Int32" />
        </SelectParameters>
    </asp:SqlDataSource>
    
  16. Passare alla visualizzazione Progettazione.

  17. Selezionare il controllo DataList e nel pannello Attività DataList fare clic su Modifica modelli.

  18. Aggiungere due controlli Button al controllo UpdatePanel all'esterno del controllo DataList.

  19. Impostare la proprietà ID del primo pulsante su Category1Button e la relativa proprietà Text su Categoria 1. Impostare la proprietà ID del secondo pulsante su Category2Button e la relativa proprietà Text su Categoria 2.

  20. Selezionare il controllo UpdatePanel e nella finestra Proprietà impostare la proprietà UpdateMode su Conditional e impostare la proprietà ChildrenAsTriggers su false.

  21. Nella casella Trigger fare clic sul pulsante con i puntini di sospensione (…) e nella finestra di dialogo Editor dell'insieme UpdatePanelTrigger aggiungere ogni pulsante della categoria come trigger del postback asincrono.

  22. Impostare il gestore eventi Click per il primo pulsante su Category1Button_Click e impostare il gestore eventi Click per il secondo pulsante su Category2Button_Click.

  23. Passare alla visualizzazione Origine e creare i seguenti gestori eventi per i due pulsanti:

    Protected Sub Category1Button_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        SqlDataSource1.SelectParameters(0).DefaultValue = "1"
    End Sub
    
    Protected Sub Category2Button_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        SqlDataSource1.SelectParameters(0).DefaultValue = "2"
    End Sub
    
    protected void Category1Button_Click(object sender, EventArgs e)
    {
        SqlDataSource1.SelectParameters[0].DefaultValue = "1";
    }
    
    protected void Category2Button_Click(object sender, EventArgs e)
    {
        SqlDataSource1.SelectParameters[0].DefaultValue = "2";
    }
    

    Il codice del gestore eventi imposta il parametro CategoryID dell'insieme SelectParameters nel controllo SqlDataSource in base al pulsante che è stato premuto. In questo modo gli utenti possono passare facilmente da una categoria all'altra.

  24. Salvare le modifiche e premere CTRL+F5 per visualizzare la pagina in un browser.

  25. Fare clic su Categoria 2 e verificare che nella pagina vengano visualizzate le nuove informazioni ma non aggiornare l'intera pagina.

    Nota:

    Non chiudere la pagina.

    <%@ Page Language="VB" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script >
    
        Protected Sub Category1Button_Click(ByVal sender As Object, ByVal e As System.EventArgs)
            SqlDataSource1.SelectParameters(0).DefaultValue = "1"
        End Sub
    
        Protected Sub Category2Button_Click(ByVal sender As Object, ByVal e As System.EventArgs)
            SqlDataSource1.SelectParameters(0).DefaultValue = "2"
        End Sub
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head >
        <title>Products Display</title>
    </head>
    <body>
        <form id="form1" >
            <div>
                <asp:ScriptManager ID="ScriptManager1" >
                </asp:ScriptManager>
                <asp:UpdatePanel ID="UpdatePanel1"  ChildrenAsTriggers="False" UpdateMode="Conditional">
                    <ContentTemplate>
                        <asp:Button ID="Category1Button"  Text="Category 1" OnClick="Category1Button_Click" />
                        <asp:Button ID="Category2Button"  OnClick="Category2Button_Click" Text="Category 2" />
                        <asp:DataList ID="DataList1"  DataKeyField="ProductID" DataSourceID="SqlDataSource1"
                            Width="231px">
                            <ItemTemplate>
                                ProductName:
                                <asp:Label ID="ProductNameLabel"  Text='<%# Eval("ProductName") %>'>
                                </asp:Label><br />
                                ProductID:
                                <asp:Label ID="ProductIDLabel"  Text='<%# Eval("ProductID") %>'></asp:Label><br />
                                <br />
                            </ItemTemplate>
                        </asp:DataList>
                        <asp:SqlDataSource ID="SqlDataSource1"  ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
                            SelectCommand="SELECT [ProductName], [ProductID] FROM [Alphabetical list of products] WHERE ([CategoryID] = @CategoryID)">
                            <SelectParameters>
                                <asp:Parameter DefaultValue="1" Name="CategoryID" Type="Int32" />
                            </SelectParameters>
                        </asp:SqlDataSource>
                    </ContentTemplate>
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="Category1Button" />
                        <asp:AsyncPostBackTrigger ControlID="Category2Button" />
                    </Triggers>
                </asp:UpdatePanel>
            </div>
        </form>
    </body>
    </html>
    
    <%@ Page Language="C#" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script >
    
        protected void Category1Button_Click(object sender, EventArgs e)
        {
            SqlDataSource1.SelectParameters[0].DefaultValue = "1";
        }
    
        protected void Category2Button_Click(object sender, EventArgs e)
        {
            SqlDataSource1.SelectParameters[0].DefaultValue = "2";
        }
    
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head >
        <title>Products Display</title>
    </head>
    <body>
        <form id="form1" >
            <div>
                <asp:ScriptManager ID="ScriptManager1" >
                </asp:ScriptManager>
                <asp:UpdatePanel ID="UpdatePanel1"  ChildrenAsTriggers="False" UpdateMode="Conditional">
                    <ContentTemplate>
                        <asp:Button ID="Category1Button"  Text="Category 1" OnClick="Category1Button_Click" />
                        <asp:Button ID="Category2Button"  OnClick="Category2Button_Click" Text="Category 2" />
                        <asp:DataList ID="DataList1"  DataKeyField="ProductID" DataSourceID="SqlDataSource1"
                            Width="231px">
                            <ItemTemplate>
                                ProductName:
                                <asp:Label ID="ProductNameLabel"  Text='<%# Eval("ProductName") %>'>
                                </asp:Label><br />
                                ProductID:
                                <asp:Label ID="ProductIDLabel"  Text='<%# Eval("ProductID") %>'></asp:Label><br />
                                <br />
                            </ItemTemplate>
                        </asp:DataList>
                        <asp:SqlDataSource ID="SqlDataSource1"  ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
                            SelectCommand="SELECT [ProductName], [ProductID] FROM [Alphabetical list of products] WHERE ([CategoryID] = @CategoryID)">
                            <SelectParameters>
                                <asp:Parameter DefaultValue="1" Name="CategoryID" Type="Int32" />
                            </SelectParameters>
                        </asp:SqlDataSource>
                    </ContentTemplate>
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="Category1Button" />
                        <asp:AsyncPostBackTrigger ControlID="Category2Button" />
                    </Triggers>
                </asp:UpdatePanel>
            </div>
        </form>
    </body>
    </html>
    

Chiamata di un servizio Web per il recupero dei dati

Verrà ora chiamato il servizio Web utilizzando il file JavaScript creato precedentemente. Il codice JavaScript utilizza i dati restituiti per popolare gli elementi DOM nel controllo UpdatePanel. Il codice server della pagina conserva i dati popolati dal servizio Web e aggiunge i dati allo stato di visualizzazione della pagina. Mantiene i dati in tutti i postback asincroni successivi.

Per utilizzare un servizio Web per restituire quantità di prodotto

  1. Nella pagina passare alla visualizzazione Progettazione.

  2. Selezionare il controllo DataList e nel pannello Attività DataList selezionare Modifica modelli.

  3. Aggiungere un controllo TextBox e un controllo Button al modello di elemento.

    Aggiungere i nuovi controlli sotto il testo e le etichette esistenti all'interno del modello.

  4. Selezionare il pulsante e nella finestra Proprietà impostare la relativa proprietà Text su Ottieni quantità da servizio Web.

    Il modello di elemento del controllo DataList deve essere simile a quello riportato nella figura seguente.

  5. Selezionare il controllo DataList, quindi nella scheda Eventi della finestra Proprietà fare doppio clic sull'evento ItemDataBound.

  6. Aggiungere il codice riportato di seguito.

    Protected Sub DataList1_ItemDataBound(ByVal sender As Object, ByVal e As DataListItemEventArgs)
        Dim label As Label = CType(e.Item.FindControl("ProductIDLabel"), Label)
        Dim button As Button = CType(e.Item.FindControl("Button1"), Button)
        Dim textbox As TextBox = CType(e.Item.FindControl("TextBox1"), TextBox)
        button.OnClientClick = "GetQuantity(" & label.Text & ",'" & textbox.ClientID & "','" & _
            label.ClientID + "','" & button.ClientID & "')"
        Dim ProductInfo As SortedList = Me.ProductInfo
        If (ProductInfo.ContainsKey(label.Text)) Then
            textbox.Text = ProductInfo(label.Text).ToString()
        End If
    End Sub
    
    protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)
    {
        Label label = (Label)e.Item.FindControl("ProductIDLabel");
        Button button = (Button)e.Item.FindControl("Button1");
        TextBox textbox = (TextBox)e.Item.FindControl("TextBox1");
        button.OnClientClick = "GetQuantity(" + label.Text + ",'" + 
            textbox.ClientID + "','" + label.ClientID + "','" + button.ClientID + "')";
        SortedList ProductInfo = this.ProductInfo;
        if (ProductInfo.ContainsKey(label.Text))
        {
            textbox.Text = ProductInfo[label.Text].ToString();
        }        
    }
    

    Il codice imposta le proprietà per i controlli in ogni oggetto DataListItem come indicato di seguito:

    • La proprietà OnClientClick del pulsante chiama una funzione JavaScript che a sua volta chiama il servizio Web.

    • Il valore della casella di testo viene impostato se una proprietà di rilevamento denominata ProductInfo contiene una chiave per l'ID del prodotto. La proprietà ProductInfo viene definita nel successivo passaggio di questa procedura.

  7. Aggiungere una proprietà denominata ProductInfo alla pagina.

    Protected Property ProductInfo() As SortedList
        Get
            If ViewState("ProductInfo") IsNot Nothing Then
                Return CType(ViewState("ProductInfo"), SortedList)
            Else
                Return New SortedList()
            End If
        End Get
        Set(ByVal value As SortedList)
            ViewState("ProductInfo") = value
        End Set
    End Property
    
    protected SortedList ProductInfo
    {
        get { return (SortedList)(ViewState["ProductInfo"] ?? new SortedList()); }
        set { ViewState["ProductInfo"] = value; }
    }
    

    Questa proprietà è un oggetto SortedList che tiene traccia dei dati aggiunti alla pagina dal servizio Web. La prima volta che viene eseguito il rendering della pagina, l'elenco è vuoto. Gli elementi possono essere aggiunti all'elenco durante i successivi postback asincroni.

  8. Aggiungere il seguente gestore eventi Page_Load:

    Protected Sub Page_Load()
        If (ScriptManager1.IsInAsyncPostBack) Then
            Dim ProductInfo As SortedList = Me.ProductInfo
            For Each d As DataListItem In DataList1.Items
                Dim label As Label = CType(d.FindControl("ProductIDLabel"), Label)
                Dim textbox As TextBox = CType(d.FindControl("TextBox1"), TextBox)
                If (textbox.Text.Length > 0) Then
                    ProductInfo(label.Text) = textbox.Text
                End If
            Next
            Me.ProductInfo = ProductInfo
        End If
    End Sub
    
    protected void Page_Load(object sender, EventArgs e)
    {
        if (ScriptManager1.IsInAsyncPostBack)
        {
            SortedList ProductInfo = this.ProductInfo;
            foreach (DataListItem d in DataList1.Items)
            {
                Label label = (Label)d.FindControl("ProductIDLabel");
                TextBox textbox = (TextBox)d.FindControl("TextBox1");
                if (textbox.Text.Length > 0)
                {
                    ProductInfo[label.Text] = textbox.Text;
                }
            }
            this.ProductInfo = ProductInfo;
        }
    }
    

    Il codice controlla se la richiesta è un postback asincrono. In caso affermativo, tutti gli elementi di dati aggiunti dal servizio Web verranno aggiunti alla proprietà ProductInfo. In questo modo è possibile tenerne traccia nello stato di visualizzazione e possono essere visualizzati nel controllo UpdatePanel durante i successivi aggiornamenti a pagina parziale. Gli elementi di dati non vengono mantenuti nei successivi postback asincroni se non ne viene tenuta traccia nello stato di visualizzazione.

  9. Passare alla visualizzazione Progettazione.

  10. Selezionare il controllo ScriptManager.

  11. Nella finestra Proprietà selezionare la proprietà Services e fare clic sul pulsante con i puntini di sospensione (…) per visualizzare la finestra di dialogo Editor dell'insieme ServiceReference.

  12. Fare clic su Aggiungi per aggiungere un riferimento al servizio.

  13. Impostare la proprietà Path del riferimento al servizio su ProductQueryService.asmx, che rappresenta il servizio Web creato precedentemente.

    Se si aggiunge un riferimento al servizio, il controllo ScriptManager genera le classi proxy client in modo da poter chiamare il servizio Web mediante JavaScript.

  14. Scegliere OK per chiudere la finestra di dialogo Editor dell'insieme ServiceReference.

  15. Selezionare il controllo ScriptManager, quindi nella finestra Proprietà selezionare la proprietà Scripts e fare clic sul pulsante con i puntini di sospensione (…) per visualizzare la finestra di dialogo Editor dell'insieme ScriptReference.

  16. Fare clic su Aggiungi per aggiungere un riferimento allo script.

  17. Impostare la proprietà Path del riferimento allo script su ProductQueryScript.js, che rappresenta il file JavaScript creato precedentemente.

    Se si aggiunge un riferimento allo script, il controllo ScriptManager inserisce lo script dopo il caricamento della Microsoft AJAX Library.

  18. Scegliere OK per chiudere la finestra di dialogo Editor dell'insieme ScriptReference.

  19. Salvare le modifiche e premere CTRL+F5 per visualizzare la pagina in un browser.

    Nella pagina vengono visualizzati i prodotti dal database Northwind con l'ID categoria 1. Le caselle di testo accanto a ogni prodotto sono vuote poiché non è stata effettuata alcuna chiamata del servizio Web.

    <%@ Page Language="VB" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script >
    
        Protected Property ProductInfo() As SortedList
            Get
                If ViewState("ProductInfo") IsNot Nothing Then
                    Return CType(ViewState("ProductInfo"), SortedList)
                Else
                    Return New SortedList()
                End If
            End Get
            Set(ByVal value As SortedList)
                ViewState("ProductInfo") = value
            End Set
        End Property
    
        Protected Sub Category1Button_Click(ByVal sender As Object, ByVal e As EventArgs)
            SqlDataSource1.SelectParameters(0).DefaultValue = "1"        
        End Sub
    
        Protected Sub Category2Button_Click(ByVal sender As Object, ByVal e As EventArgs)
            SqlDataSource1.SelectParameters(0).DefaultValue = "2"
        End Sub
    
        Protected Sub DataList1_ItemDataBound(ByVal sender As Object, ByVal e As DataListItemEventArgs)
            Dim label As Label = CType(e.Item.FindControl("ProductIDLabel"), Label)
            Dim button As Button = CType(e.Item.FindControl("Button1"), Button)
            Dim textbox As TextBox = CType(e.Item.FindControl("TextBox1"), TextBox)
            button.OnClientClick = "GetQuantity(" & label.Text & ",'" & textbox.ClientID & "','" & _
                label.ClientID + "','" & button.ClientID & "')"
            Dim ProductInfo As SortedList = Me.ProductInfo
            If (ProductInfo.ContainsKey(label.Text)) Then
                textbox.Text = ProductInfo(label.Text).ToString()
            End If
        End Sub
    
        Protected Sub Page_Load()
            If (ScriptManager1.IsInAsyncPostBack) Then
                Dim ProductInfo As SortedList = Me.ProductInfo
                For Each d As DataListItem In DataList1.Items
                    Dim label As Label = CType(d.FindControl("ProductIDLabel"), Label)
                    Dim textbox As TextBox = CType(d.FindControl("TextBox1"), TextBox)
                    If (textbox.Text.Length > 0) Then
                        ProductInfo(label.Text) = textbox.Text
                    End If
                Next
                Me.ProductInfo = ProductInfo
            End If
        End Sub
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head >
        <title>Products Display</title>
    </head>
    <body>
        <form id="form1" >
            <div>
                <asp:ScriptManager ID="ScriptManager1" >
                    <Services>
                        <asp:ServiceReference Path="ProductQueryService.asmx" />
                    </Services>
                    <Scripts>
                        <asp:ScriptReference Path="ProductQueryScript.js" />
                    </Scripts>
                </asp:ScriptManager>
                <asp:UpdatePanel ID="UpdatePanel1"  ChildrenAsTriggers="False" UpdateMode="Conditional">
                    <ContentTemplate>
                        <asp:Button ID="Category1Button"  Text="Category 1" OnClick="Category1Button_Click" />
                        <asp:Button ID="Category2Button"  OnClick="Category2Button_Click" Text="Category 2" />
                        <asp:DataList ID="DataList1"  DataKeyField="ProductID" DataSourceID="SqlDataSource1"
                            Width="400px" OnItemDataBound="DataList1_ItemDataBound">
                            <ItemTemplate>
                                ProductName:
                                <asp:Label ID="ProductNameLabel"  Text='<%# Eval("ProductName") %>'>
                                </asp:Label><br />
                                ProductID:
                                <asp:Label ID="ProductIDLabel"  Text='<%# Eval("ProductID") %>'></asp:Label><br />
                                <asp:TextBox ID="TextBox1" ></asp:TextBox>
                                <asp:Button ID="Button1"  Text="Get Quantity from Web Service" /><br />
                            </ItemTemplate>
                        </asp:DataList>
                        <asp:SqlDataSource ID="SqlDataSource1"  ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
                            SelectCommand="SELECT [ProductName], [ProductID] FROM [Alphabetical list of products] WHERE ([CategoryID] = @CategoryID)">
                            <SelectParameters>
                                <asp:Parameter DefaultValue="1" Name="CategoryID" Type="Int32" />
                            </SelectParameters>
                        </asp:SqlDataSource>
                    </ContentTemplate>
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="Category1Button" />
                        <asp:AsyncPostBackTrigger ControlID="Category2Button" />
                    </Triggers>
                </asp:UpdatePanel>
            </div>
        </form>
    </body>
    </html>
    
    <%@ Page Language="C#" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script >
    
        protected SortedList ProductInfo
        {
            get { return (SortedList)(ViewState["ProductInfo"] ?? new SortedList()); }
            set { ViewState["ProductInfo"] = value; }
        }
    
        protected void Category1Button_Click(object sender, EventArgs e)
        {
            SqlDataSource1.SelectParameters[0].DefaultValue = "1";
        }
    
        protected void Category2Button_Click(object sender, EventArgs e)
        {
            SqlDataSource1.SelectParameters[0].DefaultValue = "2";
        }
    
        protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)
        {
            Label label = (Label)e.Item.FindControl("ProductIDLabel");
            Button button = (Button)e.Item.FindControl("Button1");
            TextBox textbox = (TextBox)e.Item.FindControl("TextBox1");
            button.OnClientClick = "GetQuantity(" + label.Text + ",'" + 
                textbox.ClientID + "','" + label.ClientID + "','" + button.ClientID + "')";
            SortedList ProductInfo = this.ProductInfo;
            if (ProductInfo.ContainsKey(label.Text))
            {
                textbox.Text = ProductInfo[label.Text].ToString();
            }        
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            if (ScriptManager1.IsInAsyncPostBack)
            {
                SortedList ProductInfo = this.ProductInfo;
                foreach (DataListItem d in DataList1.Items)
                {
                    Label label = (Label)d.FindControl("ProductIDLabel");
                    TextBox textbox = (TextBox)d.FindControl("TextBox1");
                    if (textbox.Text.Length > 0)
                    {
                        ProductInfo[label.Text] = textbox.Text;
                    }
                }
                this.ProductInfo = ProductInfo;
            }
        }
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head >
        <title>Products Display</title>
    </head>
    <body>
        <form id="form1" >
            <div>
                <asp:ScriptManager ID="ScriptManager1" >
                    <Services>
                        <asp:ServiceReference Path="ProductQueryService.asmx" />
                    </Services>
                    <Scripts>
                        <asp:ScriptReference Path="ProductQueryScript.js" />
                    </Scripts>
                </asp:ScriptManager>
                <asp:UpdatePanel ID="UpdatePanel1"  ChildrenAsTriggers="False" UpdateMode="Conditional">
                    <ContentTemplate>
                        <asp:Button ID="Category1Button"  Text="Category 1" OnClick="Category1Button_Click" />
                        <asp:Button ID="Category2Button"  OnClick="Category2Button_Click" Text="Category 2" />
                        <asp:DataList ID="DataList1"  DataKeyField="ProductID" DataSourceID="SqlDataSource1"
                            Width="400px" OnItemDataBound="DataList1_ItemDataBound">
                            <ItemTemplate>
                                ProductName:
                                <asp:Label ID="ProductNameLabel"  Text='<%# Eval("ProductName") %>'>
                                </asp:Label><br />
                                ProductID:
                                <asp:Label ID="ProductIDLabel"  Text='<%# Eval("ProductID") %>'></asp:Label><br />
                                <asp:TextBox ID="TextBox1" ></asp:TextBox>
                                <asp:Button ID="Button1"  Text="Get Quantity from Web Service" /><br />
                            </ItemTemplate>
                        </asp:DataList>
                        <asp:SqlDataSource ID="SqlDataSource1"  ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
                            SelectCommand="SELECT [ProductName], [ProductID] FROM [Alphabetical list of products] WHERE ([CategoryID] = @CategoryID)">
                            <SelectParameters>
                                <asp:Parameter DefaultValue="1" Name="CategoryID" Type="Int32" />
                            </SelectParameters>
                        </asp:SqlDataSource>
                    </ContentTemplate>
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="Category1Button" />
                        <asp:AsyncPostBackTrigger ControlID="Category2Button" />
                    </Triggers>
                </asp:UpdatePanel>
            </div>
        </form>
    </body>
    </html>
    

Verifica della persistenza dei dati durante i postback asincroni

È ora possibile verificare la persistenza dei dati del servizio Web durante i postback asincroni.

Per verifica la persistenza dei dati del servizio Web durante i postback asincroni

  1. Se la pagina non è in esecuzione, premere CTRL+F5 per eseguire la pagina.

  2. Fare clic sul pulsante Ottieni quantità da servizio Web per un prodotto dell'elenco e attendere che il valore venga visualizzato nella casella di testo.

  3. Fare clic sul pulsante Categoria 2.

  4. Fare clic sul pulsante Categoria 1.

    Il valore restituito precedentemente dal servizio Web rimane visualizzato anche dopo i postback asincroni.

Verifica

In questa esercitazione è stato illustrato un esempio dell'utilizzo di un controllo UpdatePanel con un servizio Web chiamato dal codice JavaScript nel browser. Il servizio Web restituisce i dati visualizzati nel controllo UpdatePanel.

Il risultato della chiamata del servizio Web dallo script client e del popolamento degli elementi DOM utilizzando i dati restituiti è lo stesso con o senza i controlli UpdatePanel. Quando una pagina esegue un postback o quando si verifica un postback asincrono, i dati visualizzati precedentemente mediante lo script client andranno persi. Per evitare questo problema è possibile utilizzare il codice server per rendere persistenti i dati includendoli nello stato di visualizzazione. In questo modo è possibile mantenere i dati durante i successivi postback. Se i dati dal servizio Web vengono visualizzati negli elementi DOM all'esterno dei controlli UpdatePanel e non si desidera rendere persistenti i dati durante i postback asincroni, non è necessario fornire il codice server per conservare i dati.

Poiché il pulsante che ha generato la chiamata del servizio Web è all'interno del controllo UpdatePanel, la proprietà ChildrenAsTriggers viene impostata su false. Gli altri controlli di postback nel pannello vengono definiti come trigger del pannello.

Vedere anche

Concetti

Esposizione di servizi Web a script client

Chiamata a servizi Web da script client