1. 程式人生 > >記一次.net core呼叫SOAP介面遇到的問題

記一次.net core呼叫SOAP介面遇到的問題

背景

       最近需要將一些外部的Web Service及其他SOAP介面的呼叫移到一個獨立的WebAPI專案中,然後供其他.Net Core專案呼叫。之前的幾個Web Service已經成功遷移,但是在遷移一個需要使用者名稱密碼認證的SOAP介面的時候卻始終呼叫不成功。下面直接上程式碼。

示例程式碼

.net framework中通過新增服務引用會自動在web.config(或者app.config)中生成類似以下繫結配置:

<system.serviceModel>
  <bindings>
    <customBinding>
      <binding name="binding">
        <mtomMessageEncoding ="Soap11WSAddressing10" />
        <httpTransport authenticationScheme="Basic"/>
      </binding>
    </customBinding>
  </bindings>
  <client>
    <endpoint address="http://sampl.url" binding="customBinding" bindingConfiguration="binding" contract="TestClient" name="binding" />
  </client>
</system.serviceModel>

可以直接呼叫client的無參建構函式(會從配置中讀取相應的配置)來獲取客戶端例項,但是由於.net core中已經不支援web.config(或者app.config),因此需要自己通過程式碼來建立bindingEndpointAddress來獲取客戶端例項

var binding = new CustomBinding(new HttpTransportBindingElement
{
    AuthenticationScheme = AuthenticationSchemes.Basic
});

var client = new TestClient(binding, new EndpointAddress(new Uri("http://sample.url")));
client.ClientCredentials.UserName.UserName = "admin";
client.ClientCredentials.UserName.Password = "123456";

var response = client.Add(new Request()).Result

發現問題

      在測試過程中始終拋異常The server returned an invalid or unrecognized response.。使用上面相同的程式碼在.net framework裡測試卻能正常獲取響應,初步判斷應該是.net core中的問題。通過wireshark工具抓包比對,我發現了差別。

請求正常的抓包截圖
成功

請求失敗的抓包截圖
失敗

通過兩個請求的比對發現,失敗的請求頭部資訊中沒有Authorization資訊。接著我使用HttpClient傳送post請求來模擬對SOAP介面的呼叫。


httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "YWRtaW46MTIzNDU2==");

在設定和不設定Authorization的分別測試中發現設定了Authorization能夠成功請求並獲得響應,不設定Authorization的請求獲得了一段html格式的文字響應,其中有一段很說明問題HTTP 401 - Unauthorized。在這兩個不同的請求抓包中也發現成功的請求頭部中是包含Authorization資訊的,另一個則沒有。因此基本斷定問題就出現在這裡。

如何解決

      問題找到了,是因為請求頭部中缺少Authorization資訊,但是如何解決我卻始終沒有找到好的辦法,SOAP介面的呼叫不像使用HttpClient傳送post請求可以對header進行修改。直接使用HttpClient傳送post請求來呼叫SOAP介面對XML的序列化和反序列化又很是麻煩,也不想使用這種過於牽強的做法。翻遍了部落格園和stackoverfolw也始終沒有找到解決辦法。

      終於,在我不懈的努力中看到了曙光,在github上翻dotnet/wcfIssues的時候找到一些相關東西,特別是這一條https://github.com/dotnet/wcf/issues/3008。其中提到System.Private.ServiceModel版本高於或等於4.5.0的時候會拋異常The server returned an invalid or unrecognized response.,雖然他的使用跟我的不太一樣,但是異常資訊卻相同。我當即將版本降到4.4.4再次測試,結果令人驚喜,請求成功了,通過抓包分析Authorization資訊在請求頭部中。這證實我之前的判斷,就是因為沒有Authorization資訊導致請求失敗。

結語

      問題解決了,System.Private.ServiceModel4.5.0及以上版本會存在此問題,降級到4.4.4方可解決,希望微軟早日修復此問題,在NuGet包管理中看到有更新但又不能更新的包是一件很不爽的事情!