我用C#做一個接口之前測試調用、使用都沒有問題,并且對接語言也是C#,突然有一天報錯:
Server did not recognize the value of HTTP Header SOAPAction: .
搜尋找到這篇文章:http://www.tuicool.com/articles/RBVrUv
解決了我的問題,為防止文章連結失效,在這裡,拷貝原文:
Java調用.Net寫的WebService報異常:伺服器未能識别 HTTP 頭 SOAPAction 的值
異常及解決方案
使用JAX-WS調用.Net寫的WebService報了如下異常:
javax.xml.ws.soap.SOAPFaultException: System.Web.Services.Protocols.SoapException: 伺服器未能識别 HTTP 頭 SOAPAction 的值: ....
網絡上很多資訊都提示說,給.NET的WebService類(即.asmx檔案下的類)添加屬性:
[SoapDocumentService(RoutingStyle=SoapServiceRoutingStyle.RequestElement)]
即可解決。
但你知道為什麼嗎?
雖然JAVA和.NET都是實作W3C制定的WebService規範,但其實兩者在實作上并沒有完全保持一緻,在實作SOAP規範1.1中JAX-WS并不需要SOAPAction,但.NET中是需要的,哪怕是空。這就導緻了上面的異常。
那麼SOAPAction到底是作什麼的呢?
SOAPAction 被用來辨別SOAP HTTP請求的目的地。
在.NET中的實作原理是這樣的:預設情況下,.asmx 處理程式使用 SOAPAction 頭的值來執行消息排程。當用戶端調用WebService時,.asmx 處理程式會通過檢視SOAPAction确定要調用哪個方法。如:
POST /math/math.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/Add"
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://tempuri.org/">
<x>33</x>
<y>66</y>
</Add>
</soap:Body>
</soap:Envelope>
通過SOAPAction可以确定要調用Add方法。
SOAP資訊中還有種路由方式那就是使用<Body>XML 元素之後的第一個子元素,如:
POST /math/math.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: ""
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://tempuri.org/">
<x>33</x>
<y>66</y>
</Add>
</soap:Body>
</soap:Envelope>
當SOAPAction為空時,則使用<soap:Body> 第一個子元素加上其命名空間來路由:http://tempuri.org/Add。這就是上面的設定
RoutingStyle=SoapServiceRoutingStyle.RequestElement
SoapServiceRoutingStyle是枚舉類型:
- SoapAction :SOAP 消息是根據 SOAPActionHTTP 标頭路由的,預設值。
- RequestElement :SOAP 消息是根據 SOAP 消息中 <Body>XML 元素之後的第一個子元素路由的。
解決方案
是以有兩種解決方案可以處理這個異常:
- JAX-WS中加入SOAPAction并設定其值為空,可惜JAX-WS沒提供相關設定API,但CFX、axis等開源架構提供了API;
- 設定.NET不使用SOAPAction,而使用<Body>XML 元素之後的第一個子元素做為路由
RoutingStyle=SoapServiceRoutingStyle.RequestElement