2010-07-01 21 views
3

ASP.Net 2.0 Web服務自動創建SOAP 1.1和SOAP 1.2綁定。然而,我們的Web服務具有SOAP擴展和自定義異常處理,它們假定只使用SOAP 1.1綁定(例如,SOAP擴展使用HTTP SOAPAction頭來控制行爲)。ASP.Net Web服務 - 將細節元素添加到同時適用於SOAP 1.1和SOAP 1.2的SOAP錯誤響應的正確方法是什麼?

我正在尋找糾正這些假設的代碼,並使其適用於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: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響應目前對細節元件錯誤的限定名。它應該是<soap:Detail>,而只是<detail>,與SOAP 1.1響應相同。

看來,ASP.Net 2.0框架已經做了相當多的工作,將SOAPException轉換爲SOAP版本的適當形式,但忽略了正確處理detail元素。此外,它們似乎沒有像使用SoapException.DetailElementName屬性一樣提供detail元素的正確SOAP 1.2限定名稱。

那麼,將細節元素添加到同時適用於SOAP 1.1和SOAP 1.2的SOAP錯誤響應的正確方法是什麼?我是否需要自己檢測SOAP版本並對detail元素的SOAP 1.2限定名稱進行硬編碼?

回答

0

以下是註定不會被譏諷:

的修復這個問題是使用WCF。

這看起來像是ASMX Web服務處理SOAP 1.2錯誤中的detail元素時的錯誤。根據元素是否有值來改變元素的限定名稱顯然是沒有意義的。

您可以在Connect上報告此錯誤,但由於只解決了關鍵的ASMX錯誤,因此這不太可能對您有所幫助。

我懷疑WCF有這個問題,因爲它完全支持SOAP Faults。

+0

不幸的是,移除.Net 2.0目前是不可能的。 我也非常確定WCF將帶來自己的一套新問題,類似於我們已經在.asmx世界中使用自定義擴展等解決的問題。儘管如此,我一定想從長遠的角度來探索這個奢侈品。 – GBegen 2010-07-01 21:12:44

+0

@GBegen:微軟在創建WCF時從ASMX的錯誤中學習是非常愚蠢的。特別是,可擴展性模型是_far_更清晰,更全面。除此之外,您可以接管整個服務的錯誤處理,並且可以根據需要覆蓋錯誤的序列化。除了它可能不需要,因爲WCF本身支持錯誤 - 一個WCF客戶端接收到一個故障響應,並且出現一個名爲'SomeFault'的錯誤,它會收到一個'FaultException '異常。 – 2010-07-02 00:09:17

1

不知道你的問題的編碼部分,對不起,但是一個解決方法是創建禁用web.config中的soap1.2,如果你還沒有這樣看。

....

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);