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 限定名称?