你目前正处于脱机状态,正在等待 Internet 重新连接

PRB:InfoPath 无法自动向 Web 服务提交结构化 XML 数据

Support for Office 2003 has ended

Microsoft ended support for Office 2003 on April 8, 2014. This change has affected your software updates and security options. Learn what this means for you and how to stay protected.

本文已归档。它按“原样”提供,并且不再更新。
症状
当您使用内置的 InfoPath 提交功能将 InfoPath 表单中的信息提交给 Web 服务时,可能会遇到下列症状之一:
  • 您可能收到一条错误消息。您收到的错误消息根据所提交的信息和在 Web 服务上调用的方法的编码而不同。

    - 或者 -
  • 您可能注意到将意外数据提交给了 Web 服务。
本文还讨论下列内容:
  • InfoPath 如何将数据提交给 Web 服务。
  • 将 InfoPath 表单的内容提交给 Web 服务的两种方法。
原因
当 InfoPath 向 Web 服务提交数据时,它将提交被选作参数的 XML 节点的内容,但是它不会提交 XML 节点本身。这通常会正常工作。例如,您有类似下面的 Web 服务方法:
[WebMethod]   public void SendSampleString( string sampleString )   {      //Do something interesting with the sample string.   } 
如果您将以下 XML 元素提交给此 Web 服务方法,sampleString 参数将被填入 "Hello, World!"(像您期望的那样)。
<sampleElement>"Hello, World!"</sampleElement>
遗憾的是,这种情况使得很难将 XML 节点或整个 InfoPath 表单提交给 Web 服务。例如,您有类似下面的 Web 服务方法:
[WebMethod]   public string SendXMLElement( System.Xml.XmlElement theElement )   {      //Report how many children the submitted node had.      return "Node with " + theElement.ChildNodes.Count + " children submitted.";   }
如果您使用内置的 InfoPath 提交功能将示例 XML 元素提交给此方法,则 theElement 参数的内容将生成错误。出现此错误的原因是只有 XML 元素的内容 ("Hello, World!") 被发送给此 Web 服务方法。因为该字符串不是有效的 XML 元素,所以 .NET Framework 会生成错误;错误消息显示在 InfoPath 中。

如果您尝试将整个 InfoPath 表单提交给示例 Web 服务方法,则会出现类似的问题。在这种情况下,InfoPath 会提交 InfoPath 表单的所有子节点,但不会提交根节点。这导致多个顶层 XML 节点被提交。因为这也不是有效的 XML,所以 .NET Framework 选择第一个顶层 XML 节点并将它用作 theElement 参数。所有其他节点都被忽略,这造成它们没有被提交的表象。
解决方案
要避免此问题,请在脚本中编写自定义提交操作。您可以使用下列方法之一:
  • 使用辅助数据源来执行提交操作。

    - 或者 -
  • 编写用于创建自定义 SOAP 消息并将其发送给 Web 服务的代码。

使用辅助数据源

  1. 在“工具”菜单上,单击“辅助数据源”。
  2. 辅助数据源对话框中,单击“添加”。
  3. 在“数据源设置向导”的第一页上,单击“Web 服务”,然后单击“下一步”。
  4. 输入您要提交的 Web 服务的位置,然后单击“下一步”。
  5. 选择您要使用的 Web 服务方法,然后单击“下一步”。
  6. 当 InfoPath 提示您从表单中选择将用于填充 Web 服务方法的参数的域或组时,请保留这些参数为空,然后单击“下一步”。
  7. 单击以清除“当表单打开时连接到此辅助数据源”复选框,单击“完成”,然后单击“确定”关闭辅助数据源对话框。
  8. 在“工具”菜单上,单击“提交表单”。
  9. 在“提交表单”对话框中,单击“启用提交”。
  10. 在“提交”列表中,单击“使用自定义脚本提交”,然后单击“确定”打开 Microsoft 脚本编辑器。
  11. XDocument::OnSubmitRequest 方法中,使用与以下脚本类似的脚本提交整个表单。

    注意:您还可以提交表单中的个别元素。
    try{      //Get a reference to the SendXMLElement secondary data source.      var objSendXMLElement = XDocument.GetDOM("SendXMLElement");      objSendXMLElement.setProperty( "SelectionNamespaces",         'xmlns:s1="http://joelallxp.microsoft.com/schema" ' +         'xmlns:s0="http://tempuri.org/" ' +         'xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"' );       //Remove any data from the SendXMLElement secondary data source.      var objData = objSendXMLElement.selectSingleNode(         "/dfs:myFields/dfs:queryFields/s0:SendXMLElement/s0:theElement");      var objCurrentData = objData.selectNodes("@* | node()");      objCurrentData.removeAll();       //Clone the XDocument.      var objClonedDocument = XDocument.DOM.documentElement.cloneNode(true );      objData.appendChild( objClonedDocument );         //Call the "Query" method of the secondary data source to send the data.      XDocument.DataObjects("SendXMLElement").Query();         //Report the results of the submit.      XDocument.UI.Alert(          objSendXMLElement.selectSingleNode(            "/dfs:myFields/dfs:dataFields/s0:SendXMLElementResponse/s0:SendXMLElementResult").text );      eventObj.ReturnStatus = true;   }   catch(ex)   {      eventObj.ReturnStatus = false;   }

编写代码

  1. 在“工具”菜单上,单击“提交表单”。
  2. 在“提交表单”对话框中,单击“启用提交”。
  3. 在“提交”列表中,单击“使用自定义脚本提交”,然后单击“确定”打开 Microsoft 脚本编辑器。
  4. XDocument::OnSubmitRequest 方法中,使用与以下脚本类似的脚本提交整个表单。

    注意:您还可以提交表单中的个别元素。
    try   {       //Create a SOAP object.      var objSOAPConnector = new ActiveXObject("MSOSOAP.HttpConnector30");         //Set the EndPointURL property to point to the Web service.      objSOAPConnector.Property("EndPointURL") = "http://server/WebService1/Submit.asmx";       //Set the SoapAction property to point to the Web service method. You can find this URI       //in the WSDL file of the Web service.      objSOAPConnector.Property("SoapAction") = "http://tempuri.org/SendXMLElement";      objSOAPConnector.Connect();            //Begin construction of a SOAP message to send to the Web service.      objSOAPConnector.BeginMessage();       var objSOAPSerializer = new ActiveXObject("MSOSoap.SoapSerializer30");      objSOAPSerializer.Init( objSOAPConnector.InputStream );      objSOAPSerializer.startEnvelope();      objSOAPSerializer.startBody();       //Construct the structure that marks the method name and the parameter name       //that you are sending.      objSOAPSerializer.StartElement( "SendXMLElement", "http://tempuri.org/" );      objSOAPSerializer.StartElement( "theNode", "http://tempuri.org/" );       //Write out the XML of the document.      objSOAPSerializer.WriteXml( XDocument.DOM.documentElement.xml );       //Finish each element.      objSOAPSerializer.EndElement();      objSOAPSerializer.EndElement();       //Call EndMessage to complete the SOAP message and send it to the Web service method.      //This results in the Web service method being called.      objSOAPSerializer.endBody();      objSOAPSerializer.endEnvelope();       objSOAPConnector.EndMessage();       //Use a SoapReader to read the response from the Web service method .      var ResponseReader = new ActiveXObject("MSOSOAP.SoapReader30");      ResponseReader.Load( objSOAPConnector.OutputStream );       //If there was no error, return true.      if (ResponseReader.Fault != null)      {         eventObj.ReturnStatus = false;         throw "Error submitting data: " + ResponseReader.Fault.xml;      }      eventObj.ReturnStatus = true;   }    catch (ex)   {       XDocument.UI.Alert("Failed to submit document: " + ex.description);    }
这种现象是设计所导致的。
更多信息

重现问题的步骤

  1. 创建一个包含下面两个方法的 Web 服务:
    • 方法 1
      [WebMethod]   public void SendSampleString( string sampleString )   {      //Do something interesting with the sample string.   } 
    • 方法 2
      [WebMethod]   public string SendXMLElement( System.Xml.XmlElement theElement )   {      //Report how many children the submitted node had.      return "Node with " + theElement.ChildNodes.Count + " children submitted.";   }
  2. 通过选择“从数据源新建”来设计新的 InfoPath 表单。
  3. 在“数据源设置向导”中,选择“Web 服务”,然后单击“下一步”。
  4. 单击“接收和提交数据”,然后单击“下一步”。
  5. 对于接收数据 Web 服务方法,请按照下列步骤操作:
    1. 输入您先前创建的 Web 服务的 URL,然后单击“下一步”。
    2. 在“选择操作”列表中,单击“SendXMLElement”,然后单击“下一步”。
  6. 对于提交数据 Web 服务方法,请按照下列步骤操作:
    1. 输入您先前创建的 Web 服务的 URL,然后单击“下一步”。
    2. 在“选择操作”列表中,单击“SendXMLElement”,然后单击“下一步”。
  7. 单击“修改”按钮为提交操作选择一个参数。
  8. 在“dataFields”列表中,单击“SendXMLElementResult”,单击“确定”,然后单击“下一步”。
  9. 单击“先设计数据视图”,然后单击“完成”关闭“数据源设置向导”对话框。
  10. 向表单中添加 SendXMLElementResult 域。
  11. 预览表单。
  12. 发送 XML 节点结果控件中,键入 Hello, World!
  13. 在“文件”菜单上,单击“提交”。

    您将收到下面的错误消息:
    InfoPath cannot submit the form.
    An error occurred while the form was being submitted.

    Show Details:
    The SOAP response indicates that an error occurred:
    Server was unable to read request.--> There is an error in XML document (1,409).-->Specified cast is not valid.
  14. 关闭“预览”窗口,然后使表单返回设计模式。
要解决此问题,请使用本文“解决办法”一节中提到的任一方法。
属性

文章 ID:826989 - 上次审阅时间:01/11/2015 05:20:26 - 修订版本: 3.2

Microsoft Office InfoPath 2003

  • kbnosurvey kbarchive kbbug kbprb KB826989
反馈