PROBLÈME : Microsoft Office InfoPath ne peut pas utiliser un service Web qui renvoie un DataSet ADO.NET

Traductions disponibles Traductions disponibles
Numéro d'article: 822020 - Voir les produits auxquels s'applique cet article
Cet article peut contenir des liens vers des informations en langue anglaise (pas encore traduites).
Agrandir tout | Réduire tout

Sommaire

Symptômes

Lorsqu'un formulaire InfoPath est créé à partir d'un service Web qui renvoie un DataSet ADO.NET (System.Data.DataSet), InfoPath peut générer le message d'erreur suivant :

Le fichier de données XML contient des informations de schéma XML qui ne sont pas autorisées.

Cause

InfoPath ne peut pas utiliser directement les DataSets ADO.NET. InfoPath fonctionne avec les charges utiles XML génériques. Les DataSets ADO.NET renvoyés par les services Web sont sérialisés dans un format XML spécial qui empêche les DataSets ADO.NET de fonctionner directement avec InfoPath.
  • Dans le fichier de langage de définition du service Web qui définit les méthodes et les propriétés d'un service Web, le type de DataSet est représenté par une balise de schéma ouverte, <xsd:any />. InfoPath peut déduire le schéma d'un document XML renvoyé par un service Web. Pour cela, InfoPath doit toutefois effectuer un appel échantillon au service Web.
  • Un DataSet ADO.NET contient un schéma en ligne qui décrit les données qui y sont stockées. Cette version d'InfoPath ne prend pas en charge les schémas en ligne.
  • Les données d'un DataSet ADO.NET sont enveloppées dans un élément XML <diffgr:diffgram> qui n'est pas décrit dans le schéma en ligne. Les éléments XML qui contiennent les données du DataSet ADO.NET possèdent également des attributs supplémentaires qui ne sont pas décrits dans le schéma. Les données ne correspondant pas au schéma, elles ne peuvent pas être validées dans le formulaire InfoPath.
  • InfoPath n'offre pas de prise en charge intégrée du suivi des modifications semblable à un DataSet ADO.NET. Par exemple, un DataSet ADO.NET effectue le suivi des champs et des lignes qui ont été ajoutés, modifiés ou supprimés depuis la dernière acceptation des modifications. (C'est la fonction de l'élément diffgram et de l'espace de noms "diffgr" dans le flux XML.) Pour prendre en charge le suivi des modifications, InfoPath devrait soit intégrer le .NET Framework et héberger un objet DataSet pour gérer les données XML, soit réimplémenter la fonctionnalité. Ni l'une ni l'autre de ces options n'est disponible dans cette version d'InfoPath.

Résolution

Pour contourner ce problème, créez une méthode de service Web qui prend le DataSet ADO.NET renvoyé par la méthode de service Web d'origine, supprime le schéma en ligne et les éléments et attributs diffgram, puis renvoie les données XML nettoyées à InfoPath. Pour deux implémentations possibles de cette solution de contournement, reportez-vous à la section "Plus d'informations".

Statut

Ce comportement est voulu par la conception même du produit.

Plus d'informations

Procédure pour reproduire le problème

  1. Dans Microsoft Visual Studio .NET, créez un projet de service Web Microsoft  C# ASP.NET. Modifiez le nom de ce projet en NorthwindDataSet.

    Pour cela, modifiez l'emplacement en http://localhost/NorthwindDataSet.
  2. Dans le menu Projet, cliquez sur Ajouter un service Web. Nommez le nouveau service Web CustomerInfo.asmx.
  3. Ajoutez le code suivant au nouveau service Web CustomerInfo.asmx :
    /************************************************************************
       * GetCustomerInfo -- This method retrieves information from the 
       * Customer table of the Northwind database and then returns it in an
       * ADO.NET DataSet.
       * Parameters: CustomerID is the string that contains the CustomerID of the 
       *                           customer to retrieve the information for.
       * Returns: An ADO.NET DataSet that contains information about the customer.
       * *********************************************************************/
    [WebMethod]
    public System.Data.DataSet GetCustomerInfo( string CustomerID )
    {
       try
       {
          //Create a Microsoft SQL Server connection to the local SQL Server.
          System.Data.SqlClient.SqlConnection theConnection = new SqlConnection();
          theConnection.ConnectionString = "Data Source=(local);" + 
             "Integrated Security=SSPI;Initial Catalog=northwind";
          
          //Create an SQL Command to query the data.
          System.Data.SqlClient.SqlCommand theCommand = new SqlCommand();
          theCommand.Connection = theConnection;
          theCommand.CommandText = "SELECT \"CustomerID\",\"CompanyName\"," + 
             "\"ContactName\",\"ContactTitle\",\"Address\",\"City\",\"Region\"," + 
             "\"PostalCode\",\"Country\",\"Phone\",\"Fax\" FROM \"Customers\" " + 
             "WHERE CustomerID='" + CustomerID + "'";
       
          //Create an SQL DataAdapter to read the data.
          System.Data.SqlClient.SqlDataAdapter theDataAdapter = new SqlDataAdapter();
          theDataAdapter.SelectCommand = theCommand;
    
          //Open the command, and then read the data.
          theConnection.Open();
          System.Data.DataSet theCustomerInfo = new DataSet();
          theCustomerInfo.DataSetName = "CustomerInfo";
          theCustomerInfo.Namespace = "http://localhost/NorthwindDataSet/CustomerInfo";
          theDataAdapter.Fill( theCustomerInfo, "Customers" );
    
          //Clean up.
          theConnection.Close();
       
          //Return the result.
          return theCustomerInfo;
       }
       catch(Exception ex)
       {
          return null;
       }
    }
    
    L'exemple de code essaie de se connecter à un ordinateur qui exécute Microsoft SQL Server sur le même ordinateur que le service Web. En guise d'alternative, vous pouvez modifier la chaîne de connexion utilisée par l'objet System.Data.SqlConnection pour vous connecter à un autre ordinateur qui exécute SQL Server. Vous devrez peut-être configurer des autorisations SQL Server pour autoriser le service Web à accéder à la base de données. Pour plus d'informations, cliquez sur le numéro ci-dessous pour afficher l'article correspondant dans la Base de connaissances Microsoft.
    815154 COMMENT FAIRE : Configurer la sécurité SQL Server pour les applications .NET
  4. En haut de la page CustomerInfo.asmx.cs, ajoutez le code suivant aux instructions USING :
    using System.Data.SqlClient;
  5. Compilez le projet NorthwindDataSet.
  6. Démarrez InfoPath. Dans le menu Fichier, cliquez sur Créer un formulaire.
  7. Dans le volet Office Créer un formulaire, cliquez sur Nouveau à partir d'une source de données.
  8. Dans la boîte de dialogue Assistant Configuration de la source de données, sélectionnez Service Web en tant que type de source de données, puis cliquez sur Suivant.
  9. Sélectionnez Réception des données, puis cliquez sur Suivant.
  10. Tapez l'URL du service Web CustomerInfo (par exemple, http://localhost/NorthwindDataSet/CustomerInfo.asmx), puis cliquez sur Suivant.
  11. Sélectionnez la méthode GetCustomerInfo pour l'opération, puis cliquez sur Suivant.
  12. Sélectionnez le paramètre s0:CustomerID, puis cliquez sur Définir une valeur échantillon. Dans la boîte de dialogue Définir la valeur, tapez ALFKI, puis cliquez sur OK.
  13. Cliquez sur Suivant.

    Remarque InfoPath affiche le message d'erreur mentionné dans la section "Symptômes".
Pour contourner le problème, vous pouvez utiliser des étapes semblables aux suivantes pour ajouter une nouvelle méthode de service Web qui supprime les éléments incompatibles des données XML du DataSet ADO.NET. Les données XML pourront alors être utilisées par InfoPath. La méthode du service Web peut supprimer les informations du schéma en ligne des données XML ou elle peut sérialiser les données XML dans une classe wrapper fortement typée avant de les renvoyer.

Chaque méthode présente des avantages et des inconvénients.
  • Solution de contournement 1 :

    supprimer le schéma en ligne et les attributs XML incompatibles

    Cette solution de contournement est pratique car elle est simple à implémenter. En outre, si les données XML renvoyées par le service Web d'origine sont modifiées pour une raison quelconque, cette solution de contournement ne requiert aucune modification pour fonctionner avec les nouvelles données .

    Toutefois, cette solution de contournement présente également un inconvénient. Elle ne décrit pas le schéma des données XML. Par conséquent, InfoPath doit déduire le schéma à partir des données d'échantillonnage. Si celles-ci ne contiennent pas tous les éléments et attributs possibles que la méthode du service Web peut renvoyer, le schéma qu'InfoPath déduit ne contiendra pas ces éléments. Si vous exécutez une requête qui renvoie des éléments ou des attributs qui ne sont pas dans l'appel échantillon, InfoPath affiche une erreur.

    Pour implémenter la Solution de contournement 1, procédez comme suit :
    1. Dans Visual Studio .NET, ouvrez le projet NorthwindDataSet.
    2. Dans le menu Projet, cliquez sur Ajouter un service Web. Nommez le nouveau service Web IPCustomerInfo.asmx.
    3. Ajoutez le code suivant au nouveau service Web IPCustomerInfo.asmx :
      /************************************************************************
         * GetCustomerInfoNoSchema: This method calls the GetCustomerInfo
         * method of the CustomerInfo.asmx Web service, and then strips the 
         * inline schema from the resulting DataSet.
         * Parameters: CustomerID is the string that contains the CustomerID of the 
         *                           customer to retrieve information for.
         * Returns: An XML Document with no inline schema.
         * *********************************************************************/
      [WebMethod]
      public System.Xml.XmlDocument GetCustomerInfoNoSchema( string CustomerID )
      {
         //Get the core data.
         CustomerInfo theCustomerInfoService = new CustomerInfo();
         System.Data.DataSet theDataSet = 
            theCustomerInfoService.GetCustomerInfo( CustomerID );
      
         //Create a new XmlDocument from the data of the dataset.
         System.Xml.XmlDocument theDocument = new System.Xml.XmlDocument();
         theDocument.LoadXml( theDataSet.GetXml() );
      
         //Return the result.
         return theDocument;
      }
      
      L'exemple de code utilise le service Web d'origine pour fournir un DataSet ADO.NET, puis crée un document XML sans informations de schéma en ligne.
    4. Compilez le projet NorthwindDataSet.
    5. Démarrez InfoPath. Dans le menu Fichier, cliquez sur Créer un formulaire.
    6. Dans le volet Office Créer un formulaire, cliquez sur Nouveau à partir d'une source de données.
    7. Dans la boîte de dialogue Assistant Configuration de la source de données, sélectionnez Service Web en tant que type de source de données, puis cliquez sur Suivant.
    8. Sélectionnez Réception des données, puis cliquez sur Suivant.
    9. Tapez l'URL du service Web IPCustomerInfo (par exemple, http://localhost/NorthwindDataSet/IPCustomerInfo.asmx), puis cliquez sur Suivant.
    10. Sélectionnez la méthode GetCustomerInfoNoSchema pour l'opération, puis cliquez sur Suivant.
    11. Sélectionnez le paramètre s0:CustomerID, puis cliquez sur Définir une valeur échantillon. Dans la boîte de dialogue Définir la valeur, tapez ALFKI, puis cliquez sur OK.
    12. Cliquez sur Suivant, puis sur Terminer.
    13. Déplacez le champ CustomerID hors du groupe ChampsRequête dans le volet Office Source de données, puis ajoutez le champ CustomerID à l'affichage Requête.
    14. Déplacez le groupe Customers hors du groupe ChampsDonnées dans le volet Office Source de données, puis ajoutez le champ Customers à l'affichage Entrée de données. Cliquez sur Section avec contrôles.
    15. Affichez un aperçu du formulaire, puis testez-le. Notez que pour certains ID de clients tels que QUEEN, la requête rencontre des erreurs car les données d'échantillonnage ne contiennent pas tous les éléments possibles que le service Web peut renvoyer.
  • Solution de contournement 2 :

    créer une Classe wrapper fortement typée pour sérialiser les données XML du DataSet ADO.NET

    Cette solution de contournement est plus difficile à implémenter que la précédente. En outre, elle doit être adaptée à chaque méthode de service Web avec laquelle elle est utilisée et cette méthode de service Web ne doit pas modifier le schéma des données qu'elle renvoie. Toutefois, cette solution de contournement décrit le schéma des données XML qu'elle renvoie. Par conséquent, InfoPath n'est pas contraint de déduire la structure des données. Les formulaires InfoPath créés grâce à de cette solution de contournement ne sont donc pas susceptibles aux erreurs provoquées par les éléments et les attributs facultatifs.
    1. Dans Microsoft Internet Explorer, accédez à l'URL de la page test du service Web CustomerInfo (par exemple, http://localhost/NorthwindDataSet/CustomerInfo.asmx).
    2. Cliquez sur GetCustomerInfo pour accéder à la page test de cette méthode.
    3. Dans la zone de texte CustomerID, tapez ALFKI, puis cliquez sur Appeler.
    4. À partir du code XML généré, copiez l'élément <xs:schema> et tous ses enfants, puis collez-les dans un nouveau document texte dans le Bloc-notes.
    5. Supprimez les caractères - du texte collé, puis enregistrez le document en tant que CustomerInfo.xsd.
    6. Ouvrez une invite de commandes Visual Studio .NET et accédez au répertoire où vous avez enregistré CustomerInfo.xsd.
    7. Utilisez la ligne suivante pour créer une classe wrapper à partir du fichier de schéma :
      xsd.exe CustomerInfo.xsd /c /l:cs
    8. Dans Visual Studio .NET, ouvrez le projet NorthwindDataSet.
    9. Dans le menu Projet, cliquez sur Ajouter un élément existant.
    10. Accédez au fichier CustomerInfo.cs créé avec l'outil Xsd.exe, puis cliquez sur Ouvrir.
    11. Ajoutez l'espace de noms CustomerInfoWrapper autour des classes CustomerInfo et CustomerInfoCustomers.
    12. Ajoutez le code suivant au service Web IPCustomerInfo.asmx :
      /************************************************************************
         * GetCustomerInfoWrapper: This method calls the GetCustomerInfo
         * method of the CustomerInfo.asmx Web service, and then strips the 
         * inline schema from the resulting DataSet.
         * Parameters: CustomerID is the string that contains the CustomerID of the 
         *                           customer to retrieve information for.
         *                        exampleData is the wrapper class to fill with the data from the
         *                           ADO.NET DataSet.
         * Returns: none
         * *********************************************************************/
      [WebMethod]
      public void GetCustomerInfoWrapper( string CustomerID, 
         out CustomerInfoWrapper.CustomerInfo exampleData )
      {
         //Get the core data.
         CustomerInfo theCustomerInfoService = new CustomerInfo();
         System.Data.DataSet theDataSet = 
            theCustomerInfoService.GetCustomerInfo( CustomerID );
         theDataSet.Namespace = "http://localhost/NorthwindDataSet/CustomerInfo";
      
         //Create an in-memory stream to write the DataSet to.
         System.IO.MemoryStream theStream = new System.IO.MemoryStream();
      
         //Write the DataSet to the stream.
         theDataSet.WriteXml( theStream, XmlWriteMode.IgnoreSchema );
      
         //Move the streams seek pointer back to the beginning, or 
         //deserialization will fail.
         theStream.Seek(0, System.IO.SeekOrigin.Begin );
      
         //Create an XML Serializer to read the DataSet.
         System.Xml.Serialization.XmlSerializer ser = new
            System.Xml.Serialization.XmlSerializer(
               typeof(CustomerInfoWrapper.CustomerInfo));
      
         //Deserialize a CustomerInfo wrapper from the stream.
         exampleData = ((CustomerInfoWrapper.CustomerInfo)
            (ser.Deserialize( theStream )));
         return;
      }
      
      L'exemple de code utilise le service Web d'origine pour fournir un DataSet ADO.NET, puis crée un document XML sans informations de schéma en ligne.
    13. Compilez le projet NorthwindDataSet.
    14. Démarrez InfoPath. Dans le menu Fichier, cliquez sur Créer un formulaire.
    15. Dans le volet Office Créer un formulaire, cliquez sur Nouveau à partir d'une source de données.
    16. Dans la boîte de dialogue Assistant Configuration de la source de données, sélectionnez Service Web en tant que type de source de données, puis cliquez sur Suivant.
    17. Sélectionnez Réception des données, puis cliquez sur Suivant.
    18. Tapez l'URL du service Web IPCustomerInfo (par exemple, http://localhost/NorthwindDataSet/IPCustomerInfo.asmx), puis cliquez sur Suivant.
    19. Pour l'opération, sélectionnez la méthode GetCustomerInfoWrapper, puis cliquez sur Suivant.

      Notez qu'InfoPath ne vous demande pas de spécifier d'exemples de valeurs pour la méthode du service Web.
    20. Cliquez sur Terminer.
    21. Déplacez le champ CustomerID hors du groupe ChampsRequête dans le volet Office Source de données, puis ajoutez le champ CustomerID à l'affichage Requête.
    22. Déplacez le groupe Customers du groupe ChampsDonnées dans le volet Office Source de données, puis ajoutez le champ Customers à l'affichage Entrée de données.
    23. Affichez un aperçu du formulaire, puis testez-le.

      Notez que n'importe quel ID de client valide fonctionne dans ce formulaire.

Propriétés

Numéro d'article: 822020 - Dernière mise à jour: lundi 1 décembre 2003 - Version: 1.1
Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft Office InfoPath 2003
Mots-clés : 
kbprb KB822020
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.

Envoyer des commentaires

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com