Web Services 在SOAP 1.1和SOAP 1.2中,将detail元素添加到SOAP错误响应中的正确方法是什么?

q0qdq0h2  于 2022-11-15  发布在  其他
关注(0)|答案(3)|浏览(181)

ASP.Net 2.0 Web服务自动创建SOAP 1.1和SOAP 1.2绑定。但是,我们的Web服务具有SOAP扩展和自定义异常处理,它们假设只使用SOAP 1.1绑定(例如,SOAP扩展使用HTTP SOAPAction标头来控制行为)。
我希望纠正做出这些假设的代码,使其能够正确地与SOAP 1.1或SOAP 1.2一起工作。我在为SOAP错误生成元素时遇到了一点问题。
请考虑下列Web方法实作:

[WebMethod]
public void
ThrowsSoapException()
{
    throw new SoapException("This is a SOAP exception.", SoapException.ServerFaultCode);
}

透过SOAP 1.1叫用这个会产生下列结果:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Server</faultcode>
         <faultstring>This is a SOAP exception.</faultstring>
         <detail/>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

透过SOAP 1.2叫用会产生下列结果:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <soap:Fault>
         <soap:Code>
            <soap:Value>soap:Receiver</soap:Value>
         </soap:Code>
         <soap:Reason>
            <soap:Text xml:lang="en">This is a SOAP exception.</soap:Text>
         </soap:Reason>
         <soap:Detail/>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

在这两种情况下,都有一个空的detail元素作为<soap:Fault>元素的子元素,但它具有不同的限定名,即<detail><soap:Detail>
现在考虑下面的代码,它尝试创建一个带有detail元素的SOAPException。

[WebMethod]
public void
ThrowsSoapExceptionWithDetail()
{
    XmlDocument doc = new XmlDocument();
    XmlNode detail =
        doc.CreateNode(XmlNodeType.Element, SoapException.DetailElementName.Name, SoapException.DetailElementName.Namespace);
    XmlNode custom =
        doc.CreateNode(XmlNodeType.Element, "custom", "http://example.com/xml/namespace/blah");
    custom.InnerXml = "Detail value";
    detail.AppendChild(custom);
    throw new SoapException("This is a SOAP exception with a detail element.", SoapException.ServerFaultCode, Context.Request.Url.AbsoluteUri, detail);
}

SOAP 1.1响应为:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Server</faultcode>
         <faultstring>This is a SOAP exception with a detail element.</faultstring>
         <faultactor>http://localhost/simplewebservice/service1.asmx</faultactor>
         <detail>
            <custom xmlns="http://example.com/xml/namespace/blah">Detail value</custom>
         </detail>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

SOAP 1.2响应为:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <soap:Fault>
         <soap:Code>
            <soap:Value>soap:Receiver</soap:Value>
         </soap:Code>
         <soap:Reason>
            <soap:Text xml:lang="en">This is a SOAP exception with a detail element.</soap:Text>
         </soap:Reason>
         <soap:Node>http://localhost/simplewebservice/service1.asmx</soap:Node>
         <detail>
            <custom xmlns="http://example.com/xml/namespace/blah">Detail value</custom>
         </detail>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

SOAP 1.2响应现在具有错误的detail元素限定名。它应该是<soap:Detail>,但实际上只是<detail>,与SOAP 1.1响应相同。
看起来ASP.Net2.0框架在将SOAPException转换为适合SOAP版本的形式方面做了很多工作,但却忽略了正确处理detail元素。此外,它们似乎没有像处理SoapException.DetailElementName属性那样为detail元素公开正确的SOAP 1.2限定名。
那么,将detail元素添加到同时适用于SOAP 1.1和SOAP 1.2的SOAP错误响应中的正确方法是什么呢?我是否需要自己检测SOAP版本并为detail元素硬编码SOAP 1.2限定名?

9w11ddsr

9w11ddsr1#

不知道你的问题的编码部分,对不起,但是一个解决办法是在你的web.config中禁用soap1.2,如果你还没有这样做的话。

....
  <webServices>
    <protocols>
      <remove name="HttpSoap12"/>
    </protocols>
  </webServices>
rekjcdws

rekjcdws2#

以下内容并非恶意中伤:
此问题的解决方法是使用WCF。
这看起来像是ASMX Web服务在处理SOAP 1.2错误中的detail元素时出现的错误。显然,根据元素是否具有值来更改元素的限定名是没有意义的。
您可以在Connect上报告此错误,但由于只修复了关键的ASMX错误,因此这不太可能对您有所帮助。
我怀疑WCF有这个问题,因为它完全支持SOAP故障。

8ftvxx2r

8ftvxx2r3#

这是一个迟来的答案,但由于我自己也遇到过这个问题,所以我想我也可以在这里提出我的解决方案,它本质上是沿着SOAP协议的版本传递给构建错误消息的详细信息部分的方法。
从其派生ASMX Web服务类得WebService类公开SoapVersion属性,该属性包含用于发出当前SOAP请求得SOAP协议得版本.
然后可以轻松地生成适合当前SOAP版本的详细信息节。

using System.Xml.Linq;

XNamespace detailElementNamespace;
string detailElementName;
if (soapVersion == SoapProtocolVersion.Soap12)
{
    detailElementNamespace = "http://www.w3.org/2003/05/soap-envelope";
    detailElementName = "Detail";
}
else
{
    detailElementNamespace = "";
    detailElementName = "detail";
}

var document = new XmlDocument();
document.LoadXml(
    new XElement(detailElementNamespace + detailElementName,
        new XElement("MySection",
            new XElement("MyCode", "..."),
            new XElement("MyDescription", "...")
            )).ToString());

throw new SoapException(
    "MESSAGE",
    SoapException.ClientFaultCode,
    "ACTOR",
    document.DocumentElement);

相关问题