PRB:Microsoft Office InfoPath 不能使用返回 ADO.NET 数据集的 Web 服务

文章翻译 文章翻译
文章编号: 822020 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

症状

当从返回 ADO.NET 数据集 (System.Data.DataSet) 的 Web 服务创建 InfoPath 表单时,您可能会从 InfoPath 收到以下错误消息:

The XML data file contains XML Schema Information, which is not allowed.

原因

InfoPath 不能直接使用 ADO.NET 数据集。InfoPath 使用通用 XML 有效负载。由 Web 服务返回的 ADO.NET 数据集将被序列化为特殊的 XML 格式,以阻止 ADO.NET 数据集直接由 InfoPath 使用。
  • 在定义 Web 服务的方法和属性的 Web 服务定义语言文件中,数据集类型由开放架构标记 <xsd:any /> 表示。InfoPath 可以推导由 Web 服务返回的 XML 文档的架构。但是,要做到这一点,InfoPath 必须对 Web 服务进行示例调用。
  • ADO.NET 数据集包含一个内联架构,该架构描述了存储在该数据集中的数据。此版本的 InfoPath 不支持内联架构。
  • ADO.NET 数据集中的数据包装在内联架构中未予描述的 <diffgr:diffgram> XML 元素中。包含 ADO.NET 数据集数据的 XML 元素还具有其他一些未在该架构中进行描述的属性。由于数据与架构不匹配,因此无法在 InfoPath 表单中验证数据。
  • InfoPath 不对更改跟踪提供与 ADO.NET 数据集类似的内置支持。例如,ADO.NET 数据集跟踪自上次接受更改以来已经添加、更改或删除的字段和行。(这是 XML 流中的 diffgram 元素和“diffgr”名称空间的用途。)要支持更改跟踪,InfoPath 必须附带 .NET Framework 并承载一个数据集对象来管理 XML 数据,或者必须重新实现该功能。在此版本的 InfoPath 中这些选项均未提供。

解决方案

要避免此问题,请创建一个新的 Web 服务方法,使其采用从原来的 Web 服务方法返回的 ADO.NET 数据集,删除内联架构以及 diffgram 元素和属性,然后将干净的 XML 返回给 InfoPath。有关此解决办法的两种可能的实现步骤,请参阅“更多信息”部分。

状态

这种现象是设计所导致的。

更多信息

重现问题的步骤

  1. 在 Microsoft Visual Studio .NET 中,创建一个新的 Microsoft C# ASP.NET Web 服务项目。将此项目的名称更改为 NorthwindDataSet

    通过将位置更改为 http://localhost/NorthwindDataSet 可以做到这一点。
  2. 在“项目”菜单上,单击“添加 Web 服务”。将新建的 Web 服务命名为 CustomerInfo.asmx
  3. 将下面的代码添加到新建的 CustomerInfo.asmx Web 服务中:
    /************************************************************************
       * 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;
       }
    }
    
    上述示例代码尝试连接到运行 Microsoft SQL Server 且运行该 Web 服务的计算机。或者,您可以更改 System.Data.SqlConnection 对象所使用的连接字符串,以连接到其他运行 SQL Server 的计算机。您可能必须配置 SQL Server 权限才能允许 Web 服务访问数据库。 有关其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
    815154 HOW TO:Configure SQL Server Security for .NET Applications
  4. 在 CustomerInfo.asmx.cs 页面顶部,将以下代码添加到 USING 语句中:
    using System.Data.SqlClient;
  5. 编译“NorthwindDataSet”项目。
  6. 启动 InfoPath。在“文件”菜单上,单击“设计表单”。
  7. 在“设计表单”任务窗格中,单击“从数据源新建”。
  8. 在“数据源设置向导”对话框中,选择“Web 服务”作为数据源类型,然后单击“下一步”。
  9. 选择“接收数据”,然后单击“下一步”。
  10. 键入 CustomerInfo Web 服务的 URL(例如,http://localhost/NorthwindDataSet/CustomerInfo.asmx),然后单击“下一步”。
  11. 为操作选择“GetCustomerInfo”方法,然后单击“下一步”。
  12. 选择“s0:CustomerID”参数,然后单击“设置示例值...”。在“设置值”对话框中,键入 ALFKI,然后单击“确定”。
  13. 单击“下一步”。

    注意:InfoPath 将显示“症状”部分中列出的错误消息。
要避免该问题,可以使用与下面类似的步骤添加一个新的 Web 服务方法,从 ADO.NET 数据集的 XML 中删除不兼容的元素。这样做的目的是使 InfoPath 可以使用 XML 数据。该 Web 服务方法可以从 XML 数据中删除内联架构信息,或者该 Web 服务方法可以序列化强类型包装类中的 XML 数据并将其返回。

每种方法各有其优缺点。
  • 解决办法 1

    删除内联架构和不兼容的 XML 属性

    此解决办法的优点是易于实现。另外,如果原始 Web 服务返回的 XML 数据由于某种原因发生了更改,此解决办法不需要更改即可使用新数据。

    不过,此解决办法也有不足之处。它不能描述 XML 数据的架构。因此,InfoPath 必须根据示例数据推导架构。如果示例数据没有包含 Web 服务方法可以返回的所有可能的元素和属性,则 InfoPath 所推导的架构将不包含这些元素。如果您运行一个查询,该查询返回的元素或属性不在示例调用中,则 InfoPath 将显示一个错误。

    要实现解决办法 1,请执行下列步骤:
    1. 在 Visual Studio .NET 中,打开 NorthwindDataSet 项目。
    2. 在“项目”菜单上,单击“添加 Web 服务”。将新建的 Web 服务命名为 IPCustomerInfo.asmx
    3. 将下面的代码添加到新建的 IPCustomerInfo.asmx Web 服务中:
      /************************************************************************
         * 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;
      }
      
      上述示例代码使用原来的 Web 服务提供 ADO.NET 数据集,然后创建一个新的、不包含内联架构信息的 XML 文档。
    4. 编译 NorthwindDataSet 项目。
    5. 启动 InfoPath。在“文件”菜单上,单击“设计表单”。
    6. 在“设计表单”任务窗格中,单击“从数据源新建”。
    7. 在“数据源设置向导”对话框中,选择“Web 服务”作为数据源的类型,然后单击“下一步”。
    8. 选择“接收数据”,然后单击“下一步”。
    9. 键入 IPCustomerInfo Web 服务的 URL(例如,http://localhost/NorthwindDataSet/IPCustomerInfo.asmx),然后单击“下一步”。
    10. 为操作选择“GetCustomerInfoNoSchema”方法,然后单击“下一步”。
    11. 选择“s0:CustomerID”参数,然后单击“设置示例值”。在“设置值”对话框中,键入 ALFKI,然后单击“确定”。
    12. 单击“下一步”,然后单击“完成”。
    13. 在“数据源”任务窗格中,将“CustomerID”字段从“queryFields”组中移出,然后将“CustomerID”字段添加到查询视图中。
    14. 在“数据源”任务窗格中将“客户”组从“dataFields”组中移出,然后将“客户”组添加到“数据项”视图中。单击“带有控件的节”。
    15. 进行预览,然后对该表单进行测试。请注意,对于某些客户 ID(如“QUEEN”),在查询时会出现错误,因为示例数据未包含 Web 服务可以返回的所有可能的元素。
  • 解决办法 2:

    创建一个强类型的包装类,以序列化 ADO.NET 数据集的 XML 数据。

    与上一个解决办法相比,此解决办法不易实现。另外,此解决办法必须针对它所使用的每个 Web 服务方法进行定制,并且 Web 服务方法不得更改它返回的数据的架构。不过,此解决办法描述了它返回的 XML 数据的架构。因此,InfoPath 不必推导数据的结构。结果,从此解决办法中创建的 InfoPath 表单不易出现由可选元素和属性引起的错误。
    1. 在 Microsoft Internet Explorer 中,导航至 CustomerInfo Web 服务测试页的 URL(例如,http://localhost/NorthwindDataSet/CustomerInfo.asmx)。
    2. 单击“GetCustomerInfo”以导航至该方法的测试页。
    3. 在“CustomerID”文本框中,输入 ALFKI,然后单击“调用”。
    4. 从生成的 XML 中,复制“<xs:schema>”元素及其所有子元素,然后将它们粘贴到记事本的新建文本文档中。
    5. 从粘贴的文本中删除 - 字符,然后将该文档另存为 CustomerInfo.xsd
    6. 打开一个 Visual Studio .NET 命令提示符窗口,并移至您保存 CustomerInfo.xsd 的目录。
    7. 使用以下命令行根据架构文件创建一个包装类:
      xsd.exe CustomerInfo.xsd /c /l:cs
    8. 在 Visual Studio .NET 中,打开 NorthwindDataSet 项目。
    9. 在“项目”菜单上,单击“添加现有项目”。
    10. 移至用 Xsd.exe 工具创建的 CustomerInfo.cs 文件,然后单击“打开”。
    11. CustomerInfo 类和 CustomerInfoCustomers 类周围添加名称空间 CustomerInfoWrapper。
    12. 将下面的代码添加到 IPCustomerInfo.asmx Web 服务中:
      /************************************************************************
         * 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;
      }
      
      上述示例代码使用原来的 Web 服务提供一个 ADO.NET 数据集,然后创建一个新的、不包含内联架构信息的 XML 文档。
    13. 编译 NorthwindDataSet 项目。
    14. 启动 InfoPath。在“文件”菜单上,单击“设计表单”。
    15. 在“设计表单”任务窗格上,单击“从数据源新建..”。
    16. 在“数据源设置向导”对话框中,选择“Web 服务”作为数据源的类型,然后单击“下一步”。
    17. 选择“接收数据”,然后单击“下一步”。
    18. 键入 IPCustomerInfo Web 服务的 URL(例如,http://localhost/NorthwindDataSet/IPCustomerInfo.asmx),然后单击“下一步”。
    19. 为操作选择“GetCustomerInfoWrapper”方法,然后单击“下一步”。

      请注意,InfoPath 不会提示您为 Web 服务方法指定示例值。
    20. 单击“完成”。
    21. 在“数据源”任务窗格中,将“CustomerID”字段从“queryFields”组中移出,然后将“CustomerID”字段添加到“查询”视图中。
    22. 在“数据源”任务窗格中,将“客户”组从“dataFields”组中移出,然后将“客户”组添加到“数据项”视图中。
    23. 进行预览,然后对该表单进行测试。

      请注意,所有有效的客户 ID 均可在此表单中正常工作。

属性

文章编号: 822020 - 最后修改: 2003年12月5日 - 修订: 1.3
这篇文章中的信息适用于:
  • Microsoft Office InfoPath 2003
关键字:?
kbprb KB822020
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

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