SOAP 错误消息结构

后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。

SOAP 请求的响应可以采取下列两种形式之一:成功响应或错误响应。对于错误响应,响应可以包含 HTTP 错误或 SOAP 错误。成功响应始终为 SOAP 消息。有关详细信息,请参阅 SOAP 响应消息结构

对于 HTTP 错误,可能包含以下 HTTP 错误代码:“400 错误的请求(例如,标头格式无效)”。

但是,当请求在 HTTP 协议层上成功后,将由 SOAP 语言管道来处理。这并不会生成 HTTP 级别的错误响应。该语言管道开始处理请求后,可以生成的唯一错误就是 SOAP 错误。

生成 SOAP 错误后,它们将作为 HTTP 500 错误返回。在下列情况下,分析包含在请求中的 SOAP 信封时将生成这些错误:

  • SOAP 信封无效,例如分析错误、缺少元素等。

  • 分析期间出现内存不足的情况。

  • SQL Server 登录失败。

  • 不支持的 SOAP 操作,例如未找到存储过程或指定了未知操作。

  • 由于在请求中执行存储过程或用户定义函数而传递并转换的其他错误,例如指定的参数个数无效。

在 SOAP 错误响应的结构中,<faultcode> 和 <detail> 元素提供了有关错误的特定补充信息。<faultcode> 元素遵循 SOAP 1.1 和 SOAP 1.2 错误代码规范。但是,<detail> 元素包含超出 SOAP 规范的修改。它通过在 SOAP 1.1 错误的 <detail> 节点中嵌入完整的 SOAP 1.2 错误结构,为 SOAP 1.2 和 SOAP 1.1 客户端提供有关 SOAP 错误的相同的详细信息。

所有 SOAP 错误都属于下列四种情况之一:

  • 提供了详细的 SOAP 故障代码信息,但没有 SQL Server 错误消息。

    出现这种情况后,SOAP 结果将映射到相应的 SOAP 错误。

  • 提供了详细的 SOAP 故障代码,并且 <detail> 节点中包含更详细的 SQL Server 错误消息。

    一些 SQL Server 错误消息被显式处理并映射到相应的 SOAP 错误。

  • 返回了“未知 SQL 错误”SOAP 故障代码,同时 <detail> 节点中包含更详细的 SQL Server 错误消息。

    出现这种情况后,将在该代码中的某个位置生成一个 SQL 错误,但没有专门映射到特定的 SOAP 错误。

  • 返回了“未知 SQL 错误”SOAP 故障代码,但没有 SQL Server 错误消息。

    出现这种情况后,未知结果将返回某处并映射到“未知 SQL 错误”SOAP 错误。

SOAP 1.1 错误示例

<SOAP-ENV:Fault xmlns:sqlsoapfaultcode="https://schemas.microsoft.com/sqlserver/2004/SOAP/SqlSoapFaultCode">
  <faultcode>SOAP-ENV:Client</faultcode>
  <faultstring>There was an error in the incoming SOAP request packet:  Client, InvalidXml</faultstring>
  <faultactor>https://schemas.microsoft.com/sqlserver/2004/SOAP</faultactor>
  <detail xmlns:SOAP-1_2-ENV="http://www.w3.org/2003/05/soap-envelope">
    <SOAP-1_2-ENV:Code>
      <SOAP-1_2-ENV:Value>SOAP-1_2-ENV:Sender</SOAP-1_2-ENV:Value>
      <SOAP-1_2-ENV:Subcode>
         <SOAP-1_2-ENV:Value>sqlsoapfaultcode:InvalidXml</SOAP-1_2-ENV:Value>
      </SOAP-1_2-ENV:Subcode>
    </SOAP-1_2-ENV:Code>
    <SOAP-1_2-ENV:Reason>
      <SOAP-1_2-ENV:Text xml:lang="en-US">There was an error in the incoming SOAP request packet:  Sender, InvalidXml</SOAP-1_2-ENV:Text>
    </SOAP-1_2-ENV:Reason>
    <SOAP-1_2-ENV:Node>http://MyServer:80/sql</SOAP-1_2-ENV:Node>
    <SOAP-1_2-ENV:Role>https://schemas.microsoft.com/sqlserver/2004/SOAP</SOAP-1_2-ENV:Role>
    <SOAP-1_2-ENV:Detail>
      <sqlresultstream:SqlMessage xsi:type="sqlmessage:SqlMessage">
         <sqlmessage:Class>16</sqlmessage:Class>
         <sqlmessage:LineNumber>0</sqlmessage:LineNumber>
         <sqlmessage:Message>XML parsing: line 3, character 0, incorrect document syntax</sqlmessage:Message>
         <sqlmessage:Number>9422</sqlmessage:Number>
         <sqlmessage:Source>Microsoft-SQL/9.0</sqlmessage:Source>
         <sqlmessage:State>1</sqlmessage:State>
      </sqlresultstream:SqlMessage>
    </SOAP-1_2-ENV:Detail>
  </detail>
</SOAP-ENV:Fault>

示例 SOAP 1.2 错误

SOAP-1_2-ENV:Fault xmlns:sqlsoapfaultcode="https://schemas.microsoft.com/sqlserver/2004/SOAP/SqlSoapFaultCode">
  <SOAP-1_2-ENV:Code>
    <SOAP-1_2-ENV:Value>SOAP-1_2-ENV:Sender</SOAP-1_2-ENV:Value>
    <SOAP-1_2-ENV:Subcode>
      <SOAP-1_2-ENV:Value>sqlsoapfaultcode:InvalidXml</SOAP-1_2-ENV:Value>
    </SOAP-1_2-ENV:Subcode>
  </SOAP-1_2-ENV:Code>
  <SOAP-1_2-ENV:Reason>
    <SOAP-1_2-ENV:Text xml:lang="en-US">There was an error in the incoming SOAP request packet:  Sender, InvalidXml</SOAP-1_2-ENV:Text>
  </SOAP-1_2-ENV:Reason>
  <SOAP-1_2-ENV:Node>http://MyServer:80/sql</SOAP-1_2-ENV:Node>
  <SOAP-1_2-ENV:Role>https://schemas.microsoft.com/sqlserver/2004/SOAP</SOAP-1_2-ENV:Role>
  <SOAP-1_2-ENV:Detail>
    <sqlresultstream:SqlMessage xsi:type="sqlmessage:SqlMessage">
      <sqlmessage:Class>16</sqlmessage:Class>
      <sqlmessage:LineNumber>0</sqlmessage:LineNumber>
      <sqlmessage:Message>XML parsing: line 3, character 0, incorrect document syntax</sqlmessage:Message>
      <sqlmessage:Number>9422</sqlmessage:Number>
      <sqlmessage:Source>Microsoft-SQL/9.0</sqlmessage:Source>
      <sqlmessage:State>1</sqlmessage:State>
    </sqlresultstream:SqlMessage>
  </SOAP-1_2-ENV:Detail>
</SOAP-1_2-ENV:Fault>

示例

默认情况下,SQL Server 将准备 SOAP 1.2 错误信息。其中包含 SOAP 1.1 错误格式不支持的附加错误信息。因此,一些附加的 SOAP 1.2 相关错误详细信息作为溢出嵌入在 SOAP 1.1 <Details> 节点中,SOAP 1.1 客户端应用程序可以在此处分析和检索这些信息。

下列示例代码行说明了从 SQL Server 返回的 SOAP 1.1 错误中分析出此 SOAP 1.2 错误信息的一种可能的方法。事实上,此代码将用作 C# 控制台应用程序的一部分。

将分析和检索 SOAP 1.2 错误的详细信息集成到用 C# 编写的 SOAP 1.1 应用程序中

  1. 将以下代码块复制到用作 SOAP 1.1 客户端的 C# 控制台应用程序的现有函数中。

    try
    {
    ...
    }
    catch (System.Web.Services.Protocols.SoapException soapE)
    {
        // SOAP 1.1 Fault info
        Console.WriteLine("SOAP 1.1 fault...");
        Console.WriteLine("Code: " + soapE.Code.ToString());
        Console.WriteLine("Actor: " + soapE.Actor);
        Console.WriteLine("Detail: " + soapE.Detail.InnerXml);
    
        // Extract SOAP 1.2 Fault info from the Details node
        System.Xml.XmlNode fault12 = soapE.Detail;
    
    // Setup the namespace manager to use with XPath query
        System.Xml.NameTable nsTbl = new System.Xml.NameTable();
        System.Xml.XmlNamespaceManager nsMgr = new System.Xml.XmlNamespaceManager(nsTbl);
        nsMgr.AddNamespace("SOAP-1_2-ENV", "http://www.w3.org/2003/05/soap-envelope");
    
        Console.WriteLine("\r\nSOAP 1.2 fault...");
    
        // Fault Code
        // Using SelectNodes() method because SOAP 1.2 fault code are allowed to have sub-codes,
        // this way all the fault codes are retrieved at the same time.
        System.Xml.XmlNodeList myNodes = fault12.SelectNodes(".//SOAP-1_2-ENV:Value", nsMgr);
        foreach (System.Xml.XmlNode n in myNodes)
        {
            Console.WriteLine(n.ParentNode.LocalName + ": " + n.InnerText);
        }
    
        // Fault Reason
        // SOAP 1.2 fault reason can be in multiple languages which represented as sibling "Text" child
        // nodes under the "Reason" node
        myNodes = fault12.SelectNodes(".//SOAP-1_2-ENV:Reason/SOAP-1_2-ENV:Text", nsMgr);
        foreach (System.Xml.XmlNode n in myNodes)
        {
            Console.WriteLine(n.ParentNode.LocalName + ": " + n.InnerText);
        }
    
        // Fault Node
        System.Xml.XmlNode faulNode = fault12.SelectSingleNode(".//SOAP-1_2-ENV:Node", nsMgr);
        Console.WriteLine(faulNode.LocalName + ": " + faulNode.InnerText);
    
        // Fault Role
        faulNode = fault12.SelectSingleNode(".//SOAP-1_2-ENV:Role", nsMgr);
        Console.WriteLine(faulNode.LocalName + ": " + faulNode.InnerText);
    }
    
  2. 将 try { ... } 代码块的内容替换为用来向 SQL Server 发送 SOAP 1.1 请求消息的代码。如果有必要,还可以将 Console.WriteLine() 方法调用替换为应用程序中任何适于异常处理的方法调用。