在.net Core中调用SOAP服务 [英] Calling a SOAP service in .net Core

查看:765
本文介绍了在.net Core中调用SOAP服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将.net 4.6.2代码移植到 .net Core项目,该项目调用SOAP服务。在新代码中,我正在使用C#(由于某些配置原因,我现在不记得为什么)。



但是我遇到了以下异常。


收到HTTP响应 https://someurl.com/ws/Thing.pub.ws:Something
这可能是由于服务端点绑定未使用HTTP协议。
这也可能是由于服务器终止了HTTP请求上下文(可能是由于服务关闭了)。
有关更多详细信息,请参见服务器日志。


抛出该错误的代码是

  try 
{
var binding = new BasicHttpsBinding(BasicHttpsSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

var endpoint = new EndpointAddress(new Uri( https://someurl.com/ws/TheEndpoint.pub.ws:AService));

var something = new TheEndpoint.AService_PortTypeClient(binding,endpoint);
something.ClientCredentials.UserName.UserName = usrn;
something.ClientCredentials.UserName.Password =密码;

var response = await something.getSomethingAsync( id)。ConfigureAwait(false);

}
最后
{
等待的东西。CloseAsync()。ConfigureAwait(false);
}

基于工作时的旧配置,调用该服务就是这样,我缺少什么

 < bindings> 
< basicHttpsBinding>
< binding name = TheEndpoint_pub_ws_AService_Binder closeTimeout = 00:02:00
openTimeout = 00:02:00 receiveTimeout = 00:03:00 sendTimeout = 00:03: 00>
< security mode = Transport>
< transport clientCredentialType = Basic />
< message clientCredentialType = UserName algorithmSuite = Default />
< / security>
< / binding>
< / basicHttpsBinding>
< / bindings>
< client>
<终结点地址= https://someurl.com/ws/Thing.pub.ws:AService
binding = basicHttpsBinding bindingConfiguration = TheEndpoint_pub_ws_AService_Binder
contract = TheEndpoint .AService_PortType name = TheEndpoint_pub_ws_AService_Port />
< / client>

我只是无法在此网上找到很多信息。希望您能帮助我。



更新
Per Sixto Saez建议我让端点揭示了它的错误,确实是


HTTP请求未经客户端身份验证方案 Basic的授权。从服务器收到的身份验证标头是 Basic realm = Integration Server,编码= UTF-8。


I

更新2



好吧,我现在尝试使用此代码转到新语法

  ChannelFactory< IAService> factory = null; 
IAService serviceProxy = null;
Binding绑定= null;

试试
{
binding = new BasicHttpsBinding(BasicHttpsSecurityMode.Transport);

factory = new ChannelFactory< IAService>(绑定,新的EndpointAddress(new Uri( https://someurl.com/ws/TheEndpoint.pub.ws:AService))));
factory.Credentials.UserName.UserName = usrn;
factory.Credentials.UserName.Password = passw;

serviceProxy = factory.CreateChannel();

var结果=等待serviceProxy.getSomethingAsync( id)。ConfigureAwait(false);

factory.Close();
((ICommunicationObject)serviceProxy).Close();
}
catch(MessageSecurityException ex)
{
//这里捕获了错误
抛出;
}

但我仍然遇到相同(略有不同)的错误。现在它具有'Anonymous'而不是'Basic',并且现在缺少,编码= UTF-8。


客户端身份验证方案匿名对HTTP请求进行了未经授权的操作。从服务器收到的身份验证标头为基本领域=集成服务器。


是我这边还是服务器上的问题?



很明显,现在我的SOAP技能已经大大缺乏了,但是我

解决方案

几乎已经尝试了我可以用这种新方法想到的每个配置组合,但没有运气。希望有人可以向我指出正确的方向。

好吧,这个答案适用于那些试图从.net Core 项目连接到WCF 服务的人。



这是使用新的.net Core WCF语法/库解决我的问题的方法。

  BasicHttpBinding basicHttpBinding = null; 
EndpointAddre ss endpointAddress = null;
ChannelFactory< IAService> factory = null;
IAService serviceProxy = null;

试试
{
basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
endpointAddress = new EndpointAddress(new Uri( https://someurl.com/ws/TheEndpoint.pub.ws:AService));
factory = new ChannelFactory< IAService>(basicHttpBinding,EndpointAddress);

factory.Credentials.UserName.UserName = usrn;
factory.Credentials.UserName.Password = passw;
serviceProxy = factory.CreateChannel();

使用(var scope = new OperationContextScope((IContextChannel)serviceProxy))
{
var result = await serviceProxy.getSomethingAsync( id)。ConfigureAwait(false);
}

factory.Close();
((ICommunicationObject)serviceProxy).Close();
}
捕获(MessageSecurityException ex)
{
抛出;
}
获胜(异常除外)
{
掷;
}
最终
{
// //确保清理(此代码位于WCF GitHub页面上*** \\
CloseCommunicationObjects((ICommunicationObject )serviceProxy,factory);
}

UPDATE p>

我使用上面的代码得到了以下异常


此OperationContextScope被废弃了


哪个似乎是 WCF团队已损坏的东西(或需要解决的问题)。



所以我必须执行以下操作工作(基于 GitHub问题

  basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); 
basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

factory = new陈nelFactory< IAService_PortType>(basicHttpBinding,新的EndpointAddress(新的Uri( https://someurl.com/ws/TheEndpoint.pub.ws:AService))));
factory.Credentials.UserName.UserName = usern;
factory.Credentials.UserName.Password = passw;
serviceProxy = factory.CreateChannel();
((ICommunicationObject)serviceProxy).Open();
var opContext = new OperationContext((IClientChannel)serviceProxy);
var prevOpContext = OperationContext.Current; //如果无法设置,则是可选的
OperationContext.Current = opContext;

try
{
var result = await serviceProxy.getSomethingAsync( id)。ConfigureAwait(false);

//清理
factory.Close();
((ICommunicationObject)serviceProxy).Close();
}
最后
{
// ***确保清理*** \\
CloseCommunicationObjects((ICommunicationObject)serviceProxy,factory);
OperationContext.Current = prevOpContext; //或设为空,如果您没有捕获先前的上下文
}

您的要求可能会有所不同。因此,这里是您可能需要帮助您连接到WCF服务的资源:





这些测试对我有很大帮助,但它们在某些地方很难找到(我有帮助,谢谢珍兰为回答我的wcf github问题


I´m porting a .net 4.6.2 code to a .net Core project, that calls a SOAP service. In the new code I´m using C# (because of some config reasons I just can´t remember why right now).

But I´m getting the following exception.

An error occurred while receiving the HTTP response to https://someurl.com/ws/Thing.pub.ws:Something. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.

The code that is throwing it is

try
{
    var binding = new BasicHttpsBinding(BasicHttpsSecurityMode.Transport);
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

    var endpoint = new EndpointAddress(new Uri("https://someurl.com/ws/TheEndpoint.pub.ws:AService"));

    var thing= new TheEndpoint.AService_PortTypeClient(binding, endpoint);
    thing.ClientCredentials.UserName.UserName = "usrn";
    thing.ClientCredentials.UserName.Password = "passw";

    var response = await thing.getSomethingAsync("id").ConfigureAwait(false);

}
finally
{
    await thing.CloseAsync().ConfigureAwait(false);
}

Based on the old config where it works calling the service is like this, what am I missing?

<bindings>
  <basicHttpsBinding>
    <binding name="TheEndpoint_pub_ws_AService_Binder" closeTimeout="00:02:00"
        openTimeout="00:02:00" receiveTimeout="00:03:00" sendTimeout="00:03:00">
      <security mode="Transport">
        <transport clientCredentialType="Basic" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>
  </basicHttpsBinding>
</bindings>
<client>
  <endpoint address="https://someurl.com/ws/Thing.pub.ws:AService"
      binding="basicHttpsBinding" bindingConfiguration="TheEndpoint_pub_ws_AService_Binder"
      contract="TheEndpoint.AService_PortType" name="TheEndpoint_pub_ws_AService_Port" />
</client>

I´m just unable to find lot of information on this online. Hope you can help me.

UPDATE Per Sixto Saez suggestion I got the endpoint to reveal its error and it is

The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic realm="Integration Server", encoding="UTF-8"'.

I´ll try to find out what to do and post the result here if successful.

UPDATE 2

Ok now I tried to move to the new syntax with this code here

ChannelFactory<IAService> factory = null;
IAService serviceProxy = null;
Binding binding = null;

try
{
   binding = new BasicHttpsBinding(BasicHttpsSecurityMode.Transport);

   factory = new ChannelFactory<IAService>(binding, new EndpointAddress(new Uri("https://someurl.com/ws/TheEndpoint.pub.ws:AService")));            
   factory.Credentials.UserName.UserName = "usrn";
   factory.Credentials.UserName.Password = "passw";

   serviceProxy = factory.CreateChannel();

   var result = await serviceProxy.getSomethingAsync("id").ConfigureAwait(false);

    factory.Close();
    ((ICommunicationObject)serviceProxy).Close();  
}
catch (MessageSecurityException ex)
{
    //error caught here
    throw;
}

but I still get the same (slightly different) error. It now has 'Anonymous' instead of 'Basic' and is now missing ", encoding="UTF-8" at the end.

The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic realm="Integration Server"'.

Is the problem at my side or the servers?

Obviously my SOAP "skills" are greatly lacking now days, but I have just about tried every config combo I can think of with this new approach without luck. Hope somebody can point me in the right direction.

解决方案

Ok this answer is for those who are trying to connect to a WCF service from a .net Core project.

Here is the solution to my problem, using the new .net Core WCF syntax/library.

BasicHttpBinding basicHttpBinding = null;
EndpointAddress endpointAddress = null;
ChannelFactory<IAService> factory = null;
IAService serviceProxy = null;

try
{
    basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
    basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
    endpointAddress = new EndpointAddress(new Uri("https://someurl.com/ws/TheEndpoint.pub.ws:AService"));
    factory = new ChannelFactory<IAService>(basicHttpBinding, endpointAddress);

    factory.Credentials.UserName.UserName = "usrn";
    factory.Credentials.UserName.Password = "passw";
    serviceProxy = factory.CreateChannel();

    using (var scope = new OperationContextScope((IContextChannel)serviceProxy))
    {
        var result = await serviceProxy.getSomethingAsync("id").ConfigureAwait(false);
    }

    factory.Close();
    ((ICommunicationObject)serviceProxy).Close();
}
catch (MessageSecurityException ex)
{
     throw;
}
catch (Exception ex)
{
    throw;
}
finally
{
    // *** ENSURE CLEANUP (this code is at the WCF GitHub page *** \\
    CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory);
}

UPDATE

I got the following exception using the code above

This OperationContextScope is being disposed out of order.

Which seems to be something that is broken (or needs addressing) by the WCF team.

So I had to do the following to make it work (based on this GitHub issue)

basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

factory = new ChannelFactory<IAService_PortType>(basicHttpBinding, new EndpointAddress(new Uri("https://someurl.com/ws/TheEndpoint.pub.ws:AService")));
factory.Credentials.UserName.UserName = "usern";
factory.Credentials.UserName.Password = "passw";
serviceProxy = factory.CreateChannel();
((ICommunicationObject)serviceProxy).Open();
var opContext = new OperationContext((IClientChannel)serviceProxy);
var prevOpContext = OperationContext.Current; // Optional if there's no way this might already be set
OperationContext.Current = opContext;

try
{
    var result = await serviceProxy.getSomethingAsync("id").ConfigureAwait(false);

    // cleanup
    factory.Close();
    ((ICommunicationObject)serviceProxy).Close();
}
finally
{
  // *** ENSURE CLEANUP *** \\
  CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory);
  OperationContext.Current = prevOpContext; // Or set to null if you didn't capture the previous context
}

But your requirements will probably be different. So here are the resources you might need to help you connecting to your WCF service are here:

The tests helped me a lot but they where somewhat hard to find (I had help, thank you Zhenlan for answering my wcf github issue)

这篇关于在.net Core中调用SOAP服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆