Utilisation du contrôle UpdatePanel avec un service Web

Mise à jour : novembre 2007

Le contrôle UpdatePanel simplifie le rendu de page partielle dans les pages Web ASP.NET parce que les fonctionnalités AJAX d'ASP.NET gèrent des demandes de publication (postback) asynchrone et effectuent automatiquement la mise à jour. Les fonctionnalités AJAX vous permettent également d'appeler des services Web ASP.NET en utilisant ECMAScript (JavaScript) dans le navigateur. L'un des avantages de l'appel d'un service Web en utilisant le script client est que cette attente de réponse à une demande de service Web ne bloque pas le navigateur. Les utilisateurs peuvent continuer à travailler sans attendre que le service Web finisse de traiter la demande.

Ce didacticiel explique comment utiliser un service Web à l'aide d'un contrôle UpdatePanel. Une fonction JavaScript appelle le service Web pour récupérer des données et remplir des éléments DOM à l'intérieur d'un contrôle UpdatePanel à l'aide des données retournées par le service Web. Le code serveur conserve les données de service Web récupérées entre les publications asynchrones.

Cette rubrique suppose que vous êtes familiarisé avec le contrôle UpdatePanel et avec les services Web. Si ce n'est pas le cas, consultez les rubriques suivantes :

Composants requis

Pour implémenter les procédures dans votre propre environnement de développement, vous avez besoin des éléments suivants :

  • Microsoft Visual Studio 2005 ou Visual Web Developer Express.

  • Un site Web ASP.NET AJAX.

  • Accès à la base de données Northwind et chaîne de connexion nommée NorthwindConnectionString définie dans le fichier Web.config. Pour plus d'informations sur la création d'une chaîne de connexion, consultez Comment : lire les chaînes de connexion dans le fichier Web.config.

Création d'un service Web

Pour commencer, vous allez créer un service Web que vous pouvez appeler.

Pour créer un service Web et retourner des quantités de produits

  1. Dans un site Web ASP.NET AJAX, créez un nouveau fichier de service Web nommé ProductQueryService.asmx.

    Pour plus d'informations sur la création d'un service Web, consultez Appel de services Web à partir du script client.

  2. Dans le code de service Web, importez N:System.Data, N:System.Data.SqlClient, System.Configuration et les espaces de noms 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;
    

    Des types de ces espaces de noms seront utilisés dans la méthode de service Web que vous allez créer.

  3. Placez la classe ProductQueryService dans un espace de noms appelé Samples.

  4. Ajoutez l'attribut ScriptServiceAttribute à la classe.

    Cet attribut permet d'appeler le service Web à partir du script client.

  5. Remplacez la méthode par défaut HelloWorld par la méthode GetProductQuantity :

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

    Le code exécute les tâches suivantes :

    • Il crée un objet SqlConnection qui utilise une chaîne de connexion nommée NorthwindConnectionString.

    • Il crée un objet SqlCommand qui contient une commande SQL pour récupérer le nombre d'unités en stock pour un ID de produit spécifié.

    • Il définit la valeur de retour à une chaîne utilisée comme réponse renvoyée au navigateur.

      Remarque :

      Dans le cadre de ce didacticiel, la méthode Web introduit un délai artificiel. Dans la pratique, vous n'introduiriez pas de délai. Au lieu de cela, le délai aurait pour cause le trafic sur le serveur ou le temps de traitement d'un code de service Web plus long que d'habitude, pour une requête de base de données par exemple.

  6. Enregistrez vos modifications et appuyez sur CTRL+F5 pour afficher la page dans un navigateur.

  7. Cliquez sur le lien GetProductQuantity pour appeler la méthode Web.

  8. Entrez 6 dans la zone ProductID puis cliquez sur Appeler.

    La quantité du produit est retournée sous forme XML dans le navigateur. Elle montre que le service Web fonctionne comme prévu.

    <%@ 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;
            }
        }
    }
    

Création de code JavaScript pour appeler le service Web

Dans cette procédure, vous allez créer un fichier JavaScript qui appelle le service Web que vous avez créé dans la procédure précédente.

Pour créer un fichier JavaScript afin d'utiliser le service Web

  1. Créez un nouveau fichier JScript nommé ProductQueryScript.js.

  2. Ajoutez le script suivant au fichier :

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

    Le script effectue les tâches suivantes :

    • Il crée une fonction nommée GetQuantity qui appelle la méthode de service Web GetProductQuantity.

    • Il crée une fonction nommée OnSucceeded et appelée lorsque l'appel de service Web retourne un résultat.

Création d'une page Web pour afficher des données

Ensuite, vous allez créer une page Web qui contient un contrôle UpdatePanel. Les contrôles à l'intérieur du contrôle UpdatePanel affichent des informations concernant le produit de la base de données Northwind.

Pour créer une page Web pour afficher des produits

  1. Créez une nouvelle page Web et basculez en mode Design.

  2. Sous l'onglet Extensions AJAX de la boîte à outils, double-cliquez sur le contrôle ScriptManager pour l'ajouter à la page.

  3. Double-cliquez sur le contrôle UpdatePanel dans la boîte à outils pour ajouter un contrôle UpdatePanel à la page.

  4. Cliquez à l'intérieur du contrôle UpdatePanel, puis, sous l'onglet Données de la boîte à outils, double-cliquez sur le contrôle DataList.

  5. Dans le panneau Tâches DataList, dans la liste Choisir la source de données, sélectionnez <Nouvelle source de données... >.

    Remarque :

    Si vous ne voyez pas le panneau Tâches DataList, cliquez avec le bouton droit sur le contrôle DataList et sélectionnez Afficher la balise active.

    L'Assistant Configuration de source de données s'affiche.

  6. Sélectionnez Base de données, acceptez le nom par défaut SqlDataSource1, puis cliquez sur OK.

  7. Dans la liste Quelle connexion de données votre application doit-elle utiliser pour établir une connexion à la base de données, sélectionnez NorthwindConnectionString, puis cliquez sur Suivant.

  8. Sous Comment souhaitez-vous extraire les données de votre base de données, sélectionnez Spécifiez les colonnes d'une table ou d'une vue, sélectionnez Products dans la liste et, dans la liste Colonnes, sélectionnez ProductID et ProductName.

  9. Cliquez sur le bouton WHERE.

    La boîte de dialogue Ajouter une clause WHERE s'affiche.

  10. Dans la liste Colonnes, sélectionnez CategoryID et dans la liste Source, choisissez Aucune.

  11. Dans la section Propriétés du paramètre de la boîte de dialogue, dans la zone de texte Valeur, entrez 1.

  12. Cliquez Ajouter pour ajouter la clause WHERE à l'instruction SQL.

  13. Cliquez sur OK pour fermer la boîte de dialogue Ajouter une clause WHERE.

  14. Cliquez sur Suivant, puis sur Terminer pour fermer l'Assistant.

  15. Basculez en mode Source et vérifiez que le contrôle SqlDataSource est comparable à l'exemple suivant :

    <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. Basculez en mode Design.

  17. Sélectionnez le contrôle DataList et, dans le panneau Tâches DataList, cliquez sur Modifier les modèles.

  18. Ajoutez deux contrôles Button au contrôle UpdatePanel à l'extérieur du contrôle DataList.

  19. Affectez à la propriété ID du premier bouton la valeur Category1Button et à sa propriété Text la valeur Catégorie 1. Affectez à la propriété ID du deuxième bouton la valeur Category2Button et à sa propriété Text la valeur Catégorie 2.

  20. Sélectionnez le contrôle UpdatePanel et, dans la fenêtre Propriétés, affectez à la propriété UpdateMode la valeur Conditional, puis à la propriété ChildrenAsTriggers la valeur false.

  21. Dans la zone Déclencheurs, cliquez sur le bouton de sélection (...) et, dans la boîte de dialogue Éditeur de collections UpdatePanelTrigger, ajoutez chaque bouton de catégorie sous forme de déclencheur de publication asynchrone.

  22. Affectez au gestionnaire d'événements Click du premier bouton la valeur Category1Button_Click et au gestionnaire d'événements Click du deuxième bouton la valeur Category2Button_Click.

  23. Basculez en mode Source et créez les gestionnaires d'événements suivants pour les deux boutons :

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

    Les jeux de codes du gestionnaire d'événements définissent le paramètre CategoryID de la collection SelectParameters dans le contrôle SqlDataSource en fonction du bouton sélectionné. Les utilisateurs peuvent ainsi basculer d'une catégorie à l'autre.

  24. Enregistrez vos modifications et appuyez sur CTRL+F5 pour afficher la page dans un navigateur.

  25. Cliquez sur Catégorie 2 et vérifiez que la page affiche de nouvelles informations mais n'actualise pas la page entière.

    Remarque :

    Ne fermez pas la page.

    <%@ 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>
    

Appel d'un service Web pour récupérer les données

Vous allez maintenant appeler le service Web en utilisant le fichier JavaScript que vous avez créé précédemment. Le code Javascript utilise les données retournées pour remplir des éléments DOM à l'intérieur du contrôle UpdatePanel. Le code serveur de la page conserve des données remplies à partir du service Web et les ajoute à la vue d'état de la page. Les données sont ainsi conservées dans les publications asynchrones suivantes.

Pour utiliser un service Web et retourner des quantités de produits

  1. Dans la page, basculez en mode Design.

  2. Sélectionnez le contrôle DataList et, dans le panneau Tâches DataList, sélectionnez Modifier les modèles.

  3. Ajoutez un TextBox et un contrôle Button au modèle d'élément.

    Ajoutez les nouveaux contrôles sous le texte et les étiquettes existants du modèle.

  4. Sélectionnez le bouton et, dans la fenêtre Propriétés, affectez à la propriété Text la valeur Acquisition de la quantité à partir du service Web.

    Le modèle d'élément du contrôle DataList doit être comparable à celui illustré ci-dessous.

  5. Sélectionnez le contrôle DataList et, sous l'onglet Événements de la fenêtre Propriétés, double-cliques sur l'événement ItemDataBound.

  6. Ajoutez le code ci-dessous :

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

    Le code définit les propriétés des contrôles dans chaque objet DataListItem, comme suit :

    • La propriété OnClientClick du bouton appelle une fonction JavaScript qui appelle ensuite le service Web.

    • La valeur de la zone de texte est définie si une propriété de suivi nommée ProductInfo contient une clé pour l'ID de produit. La propriété ProductInfo est définie dans l'étape suivante de cette procédure.

  7. Ajoutez une propriété nommée ProductInfo à la page.

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

    Cette propriété est un objet SortedList qui suit les données ajoutées à la page du service Web. La première fois que la page est rendue, la liste est vide. Pendant des publications asynchrones suivantes, les éléments peuvent être ajoutés à la liste.

  8. Ajoutez le gestionnaire d'événements Page_Load suivant :

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

    Le code contrôle si la demande est une publication asynchrone. Si c'est le cas, tous les éléments de données ajoutés par le service Web sont ajoutés à la propriété ProductInfo. Ils sont ainsi activés pour être suivis dans l'état d'affichage et affichés dans UpdatePanel pendant les mises à jour de pages partielles suivantes. Si les éléments de données ne sont pas suivis dans l'état d'affichage, ils ne sont pas conservés dans les publications asynchrones suivantes.

  9. Basculez en mode Design.

  10. Sélectionnez le contrôle ScriptManager.

  11. Dans la fenêtre Propriétés, sélectionnez la propriété Services et cliquez sur le bouton de sélection (…) pour afficher la boîte de dialogue Éditeur de collections ServiceReference.

  12. Cliquez sur Ajouter pour ajouter une référence de service.

  13. Affectez à la propriété Path de la référence de service la valeur ProductQueryService.asmx, qui est le service Web que vous avez créé précédemment.

    L'ajout d'une référence de service oblige le contrôle ScriptManager à générer des classes de proxy client afin que le service Web puisse être appelé en utilisant JavaScript.

  14. Cliquez sur OK pour fermer la boîte de dialogue Éditeur de collections ServiceReference.

  15. Sélectionnez le contrôle ScriptManager et, dans la fenêtre Propriétés, sélectionnez la propriété Scripts, puis cliquez sur le bouton de sélection (…) pour afficher la boîte de dialogue Éditeur de collections ScriptReference.

  16. Cliquez sur Ajouter pour ajouter une référence de script.

  17. Affectez la valeur ProductQueryScript.js.js à la propriété Path de la référence de script, c'est-à-dire le fichier JavaScript que vous avez créé précédemment.

    L'ajout d'une référence de script oblige le contrôle ScriptManager à insérer le script une fois le chargement de Microsoft AJAX Library terminé.

  18. Cliquez sur OK pour fermer la boîte de dialogue Éditeur de collections ScriptReference.

  19. Enregistrez vos modifications et appuyez sur CTRL+F5 pour afficher la page dans un navigateur.

    La page affiche les produits de la base de données Northwind dont l'ID de catégorie est 1. Les zones de texte à côté de chaque produit sont vides parce qu'aucun appel de service Web n'a été fait.

    <%@ 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>
    

Vérification de la persistance des données durant les publications asynchrones

Vous pouvez maintenant voir comment les données du service Web sont rendues persistantes pendant des publications asynchrones.

Pour vérifier que les données de service Web sont rendues persistantes pendant es publications asynchrones

  1. Si la page ne s'exécute pas déjà, appuyez sur CTRL+F5 pour exécuter la page.

  2. Cliquez sur le bouton Acquisition de quantité de la quantité à partir du service Web pour tout produit dans la liste, puis attendez que la valeur s'affiche dans la zone de texte.

  3. Cliquez sur le bouton Catégorie 2.

  4. Cliquez sur le bouton Catégorie 1.

    Remarquez que la valeur retournée précédemment par le service Web apparaît encore, même après les publications asynchrones.

Récapitulatif

Ce didacticiel a illustré un exemple d'utilisation d'un contrôle UpdatePanel avec un service Web appelé à partir du code Javascript dans le navigateur. Le service Web retourne des données affichées à l'intérieur du contrôle UpdatePanel.

Le résultat de l'appel du service Web à partir du script client et du remplissage d'éléments DOM à l'aide des données retournées est le même avec ou sans contrôles UpdatePanel. Lorsqu'une page exécute une publication ou lorsqu'une publication asynchrone se produit, les données affichées précédemment en utilisant le script client sont perdues. Pour éviter ce problème, vous pouvez utiliser le code serveur pour rendre les données persistantes en l'intégrant à l'état d'affichage. Cela vous permet de maintenir les données pendant des publications suivantes. Si les données du service Web sont affichées dans les éléments DOM à l'extérieur des contrôles UpdatePanel et vous ne souhaitez pas rendre les données persistantes pendant des publications asynchrones, vous n'avez pas à fournir le code serveur pour les maintenir.

Parce que le bouton qui a déclenché l'appel de service Web est à l'intérieur du contrôle UpdatePanel, la propriété ChildrenAsTriggers a la valeur false. D'autres contrôles de publication à l'intérieur du panneau sont définis comme déclencheurs pour le panneau.

Voir aussi

Concepts

Exposition de services Web au script client

Appel de services Web à partir du script client