天天看點

C#WebService異常:伺服器未能識别 HTTP 頭 SOAPAction 的值

我用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是枚舉類型:

  1. SoapAction :SOAP 消息是根據 SOAPActionHTTP 标頭路由的,預設值。
  2. RequestElement :SOAP 消息是根據 SOAP 消息中 <Body>XML 元素之後的第一個子元素路由的。

解決方案 

是以有兩種解決方案可以處理這個異常:

  1. JAX-WS中加入SOAPAction并設定其值為空,可惜JAX-WS沒提供相關設定API,但CFX、axis等開源架構提供了API;
  2. 設定.NET不使用SOAPAction,而使用<Body>XML 元素之後的第一個子元素做為路由
    RoutingStyle=SoapServiceRoutingStyle.RequestElement