3

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>

现在考虑以下代码,它尝试使用详细元素创建 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 响应现在具有错误的详细信息元素限定名称。它应该<soap:Detail>,但仅仅是<detail>,与 SOAP 1.1 响应相同。

似乎 ASP.Net 2.0 框架在将 SOAPException 转换为 SOAP 版本的适当形式方面做了很多工作,但忽略了正确处理 detail 元素。此外,它们似乎没有像使用 SoapException.DetailElementName 属性那样为详细元素公开正确的 SOAP 1.2 限定名称。

那么,将详细元素添加到适用于 SOAP 1.1 和 SOAP 1.2 的 SOAP 错误响应的正确方法是什么?我是否需要自己检测 SOAP 版本并为 detail 元素硬编码 SOAP 1.2 限定名称?

4

3 回答 3

1

不知道你问题的编码部分,抱歉,如果你还没有这样看,一个解决方法是禁用你的 web.config 中的 soap1.2。

……

于 2010-12-15T10:55:33.867 回答
0

以下内容并不意味着讽刺:

解决此问题的方法是使用 WCF。

这看起来像是 ASMX Web 服务处理 SOAP 1.2 故障中的 detail 元素中的错误。显然,根据元素是否具有值来更改元素的限定名称是没有意义的。

您可以在Connect上报告此错误,但由于只修复了关键的 ASMX 错误,因此不太可能对您有所帮助。

我怀疑 WCF 有这个问题,因为它完全支持 SOAP 错误。

于 2010-07-01T19:24:29.197 回答
0

这是一个较晚的答案,但由于我自己遇到了这个问题,我想我不妨把我的解决方案放在这里,它本质上是将 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);
于 2015-11-19T18:14:58.223 回答