记一次.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
),因此需要自己通过代码来创建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
的时候找到一些相关东西,特别是这一条。其中提到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包管理中看到有更新但又不能更新的包是一件很不爽的事情!