首页 文章

在.net Core中调用SOAP服务

提问于
浏览
17

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

但我得到以下例外 .

接收到https://someurl.com/ws/Thing.pub.ws:Something的HTTP响应时发生错误 . 这可能是由于服务 endpoints 绑定不使用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 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);
}

它基于旧的配置工作,调用服务是这样的, 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>

我无法在网上找到很多这方面的信息 . 希望您能够帮助我 .

UPDATE Per Sixto Saez建议我得到了 endpoints 以显示其错误,它是

HTTP请求未经授权使用客户端身份验证方案“Basic” . 从服务器接收的认证头是'Basic realm =“Integration Server”,encoding =“UTF-8”' .

如果成功,我会尝试找出要做的事情并将结果发布在此处 .

UPDATE 2

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

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;
}

但我仍然得到相同(略有不同)的错误 . 它现在有'Anonymous'而不是'Basic',现在最后缺少“,encoding =”UTF-8“ .

HTTP请求未经授权,客户端身份验证方案为“匿名” . 从服务器收到的身份验证标头是'Basic realm =“Integration Server”' .

Is the problem at my side or the servers?

显然,我的SOAP“技能”现在非常缺乏,但我只是尝试了一下我能用这种新方法想到的每个配置组合而没有运气 . 希望有人能指出我正确的方向 .

3 回答

  • 2

    好的,这个答案适用于那些试图连接 to a WCF service from a .net Core 项目的人 .

    以下是 my 问题的解决方案,使用新的.net Core WCF语法/库 .

    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

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

    此OperationContextScope正在按顺序处理 .

    这似乎是WCF团队的something that is broken(或需要解决) .

    因此,我必须执行以下操作才能使其正常工作(基于此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
    }
    

    但您的要求可能会有所不同 . 以下是帮助您连接到WCF服务可能需要的资源:

    这些测试给了我很多帮助,但是他们有点难找(我得到了帮助,感谢Zhenlan的answering my wcf github issue

  • 17

    要从.NET核心使用SOAP服务,从项目UI添加连接的服务不起作用 .

    Option 1: Use dotnet-svcutil CLI. Prerequisite: VS 2017, Version 15.5 or above

    • 启动开发人员命令提示符VS 2017 .

    • 转到app.csproj文件并添加以下参考:

    <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.9" />
    <PackageReference Include="System.ServiceModel.Http" Version="4.5.3" />
    </ItemGroup>
    <ItemGroup>
    <DotNetCliToolReference Include="dotnet-svcutil" Version="1.0.*" />
    </ItemGroup>
    
    • 重建解决方案 .

    • 从VS命令提示符将目录更改为项目位置 .

    • run命令:svcutil SOAP_URL?wsdl;示例:example.com/test/testing?wsdl这将在项目中生成参考文件和output.config文件 .

    • .Net Core没有任何app.config或web.config文件,但output.config文件将提供SOAP绑定 .

    Option 2 In case you need to refer more than one SOAP sevice,

    • 创建一个新的类库项目,使用.Net framework 4.5.1 .Net框架很重要,因为如果.Net Framework是最新的,我看到 Contract 生成的参考文件不正确 .

    • 右键单击“引用”以添加服务引用 .

    • 从.Net核心项目中引用类库项目 .

  • 4

    对于那些试图对NTLM和.Net Core做同样事情并且想知道某些变量被定义为什么的人,我澄清了代码如下:

    IAService_PortType 是您按照https://joshuachini.com/2017/07/13/calling-a-soap-service-from-asp-net-core-or-net-core/上的指南创建的服务参考

    BasicHttpBinding basicHttpBinding = 
        new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
    // Setting it to Transport will give an exception if the url is not https
    basicHttpBinding.Security.Transport.ClientCredentialType = 
        HttpClientCredentialType.Ntlm;
    
    ChannelFactory<IAService_PortType> factory = 
        new ChannelFactory<IAService_PortType>(basicHttpBinding, 
        new EndpointAddress(
            new Uri("https://someurl.com/ws/TheEndpoint.pub.ws:AService")));
    factory.Credentials.Windows.ClientCredential.Domain = domain;
    factory.Credentials.Windows.ClientCredential.UserName = user;
    factory.Credentials.Windows.ClientCredential.Password = pass;
    IAService_PortType serviceProxy = factory.CreateChannel();
    ((ICommunicationObject)serviceProxy).Open();
    
    try
    {
        var result = serviceProxy.getSomethingAsync("id").Result;
    
    }
    finally
    {
        // cleanup
        factory.Close();
        ((ICommunicationObject)serviceProxy).Close();
    }
    

相关问题