背景 最近需要將一些外部的 及其他 介面的調用移到一個獨立的 項目中,然後供其他 項目調用。之前的幾個 已經成功遷移,但是在遷移一個需要用戶名密碼認證的 介面的時候卻始終調用不成功。下麵直接上代碼。 示例代碼 在 中 ...
背景
最近需要將一些外部的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
),因此需要自己通過代碼來創建binding
和EndpointAddress
來獲取客戶端實例
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/wcf
的Issues
的時候找到一些相關東西,特別是這一條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.ServiceModel
4.5.0及以上版本會存在此問題,降級到4.4.4方可解決,希望微軟早日修複此問題,在NuGet包管理中看到有更新但又不能更新的包是一件很不爽的事情!