Consuming WCF service from .net core 2.1 web app
Asked Answered
C

0

6

I have a .net framework app that consumes a WCF service successfully, and when i try to duplicate the settings onto my .net standard 2.0 class library - which is used by a .net core 2.1 web application - i get various errors depending on how i set it up.

Firstly, this is the working consumer configuration:

<netTcpBinding>
<binding name="netTcpBinding_Service" closeTimeout="00:10:00" openTimeout="00:40:00" receiveTimeout="00:32:00" sendTimeout="00:10:00" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647">
  <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
  <reliableSession ordered="true" inactivityTimeout="00:10:00" />
  <security mode="TransportWithMessageCredential">
    <message clientCredentialType="Certificate" algorithmSuite="Default" />
    <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
  </security>
</binding>
</netTcpBinding>
<behaviors>
  <endpointBehaviors>
    <behavior name="ClientBehavior">
      <clientCredentials>
        <clientCertificate findValue="Client" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
        <serviceCertificate>
          <defaultCertificate findValue="Server" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
          <authentication certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck" />
        </serviceCertificate>
      </clientCredentials>
      <dataContractSerializer maxItemsInObjectGraph="2147483647" />
    </behavior>
  </endpointBehaviors>
</behaviors>
      <endpoint address="net.Tcp://localhost:8004/Service" behaviorConfiguration="ClientBehavior" binding="netTcpBinding" bindingConfiguration="netTcpBinding_RACService" contract="ServiceInterfaces.IRACService" name="IService">
    <identity>
      <dns value="Server" />
    </identity>

Scenario 1: Attempt to duplicate the settings as much as i could:

    private static NetTcpBinding CreateNetTcpBinding()
    {
        var security = new NetTcpSecurity
        {
            Message = new MessageSecurityOverTcp(),
            Transport = new TcpTransportSecurity()
        };
        security.Message.ClientCredentialType = MessageCredentialType.Certificate;
        security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
        security.Transport.SslProtocols |= SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;

        security.Mode = SecurityMode.TransportWithMessageCredential;

        var binding = new NetTcpBinding
        {
            CloseTimeout = new TimeSpan(0, 10, 0),
            OpenTimeout = new TimeSpan(0, 40, 0),
            ReceiveTimeout = new TimeSpan(0, 32, 0),
            Name = "NetTcpBinding",
            SendTimeout = new TimeSpan(0, 10, 0),
            MaxBufferPoolSize = 524288,
            MaxReceivedMessageSize = 2147483647,
            Security = security,
        };

        return binding;
    }

Getting exception for this line: security.Message.ClientCredentialType = MessageCredentialType.Certificate; Exception:

{System.PlatformNotSupportedException: MessageSecurityOverTcp.ClientCredentialType is not supported for values other than 'MessageCredentialType.None'. at System.ServiceModel.MessageSecurityOverTcp.set_ClientCredentialType(MessageCredentialType value)


Scenario 2: Changed MessageCrendentialType to None

private static NetTcpBinding CreateNetTcpBinding()
{
    var security = new NetTcpSecurity
    {
        Message = new MessageSecurityOverTcp(),
        Transport = new TcpTransportSecurity()
    };
    security.Message.ClientCredentialType = MessageCredentialType.None;
    security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
    security.Transport.SslProtocols |= SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;

    security.Mode = SecurityMode.TransportWithMessageCredential;

    var binding = new NetTcpBinding
    {
        CloseTimeout = new TimeSpan(0, 10, 0),
        OpenTimeout = new TimeSpan(0, 40, 0),
        ReceiveTimeout = new TimeSpan(0, 32, 0),
        Name = "NetTcpBinding",
        SendTimeout = new TimeSpan(0, 10, 0),
        MaxBufferPoolSize = 524288,
        MaxReceivedMessageSize = 2147483647,
        Security = security,
    };

    return binding;
}

private static EndpointAddress CreateEndpoint()
{
    var identity = new DnsEndpointIdentity("Server");
    var uri = new Uri("net.Tcp://localhost:8004/Service");
    var endpoint = new EndpointAddress(uri, identity);

    return endpoint;
}
public static ServiceProxy CreateClientProxy(string url)
{
    ServiceProxy racServiceProxy;
    racServiceProxyStore.TryGetValue(url, out racServiceProxy);

    try
    {
        if ((racServiceProxy != null) && (racServiceProxy.State == CommunicationState.Faulted ||
                                          racServiceProxy.State == CommunicationState.Closed))
        {
            racServiceProxy.Abort();
            racServiceProxy = null;
        }
        if (racServiceProxy == null)
        {
            CallBackProxy cb = new CallBackProxy();
            InstanceContext ctx = new InstanceContext(cb);

            var binding = CreateNetTcpBinding();
            var endpoint = CreateEndpoint();
            racServiceProxy = new ServiceProxy(ctx, binding, endpoint);
            racServiceProxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "Client");

        }
    }
    catch (InvalidOperationException ex)
    {
        throw;
    }
    catch (Exception ex)
    {
    }
    return racServiceProxy;
}

public void InvokeService(IWCFMessage message, OnStatusReceived onStatusReceived, OnResultReceived onResultReceived)
{
    try
    {
        Guid processId = ((WCFMessage)message).ProcessID;

        callBackProxy.AddEvents(onStatusReceived, onResultReceived, processId);

        if (this.State == CommunicationState.Opened || this.State == CommunicationState.Created)
        {
            if (this.State == CommunicationState.Created)
                this.ChannelFactory.Open();

            base.Channel.InvokeRACService(message);
        }
        else
        {
            throw new RacServiceProxyChannelException("Channel Faulted", (int)this.State);
        }
    }

Getting exception on: this.ChannelFactory.Open();. If i skip over this line, i get exception on: base.Channel.InvokeRACService(message); The exception:

{System.PlatformNotSupportedException: NetTcpBinding.CreateMessageSecurity is not supported. at System.ServiceModel.NetTcpBinding.CreateMessageSecurity() at System.ServiceModel.NetTcpBinding.CreateBindingElements() at System.ServiceModel.Channels.Binding.EnsureInvariants(String contractName) at System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory(ServiceEndpoint serviceEndpoint, Boolean useActiveAutoClose) at System.ServiceModel.ChannelFactory.OnOpening() at System.ServiceModel.Channels.CommunicationObject.System.ServiceModel.IAsyncCommunicationObject.OpenAsync(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.OpenAsyncInternal(TimeSpan timeout) at System.ServiceModel.ChannelFactory.EnsureOpened() at System.ServiceModel.DuplexChannelFactory1.CreateChannel(InstanceContext callbackInstance, EndpointAddress address, Uri via) at System.ServiceModel.ClientBase1.get_Channel()}


Scenario 3: Changing security mode: security.Mode = SecurityMode.None; (in method CreateNetTcpBinding)

Getting exception when invoking the service base.Channel.InvokeService(message); The exception:

{System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:09:59.8599605'. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at System.ServiceModel.Channels.SocketConnection.HandleReceiveAsyncCompleted() at System.ServiceModel.Channels.SocketConnection.BeginReadCore(Int32 offset, Int32 size, TimeSpan timeout, Action1 callback, Object state) --- End of inner exception stack trace --- at System.ServiceModel.Channels.SocketConnection.BeginReadCore(Int32 offset, Int32 size, TimeSpan timeout, Action1 callback, Object state) at System.ServiceModel.Channels.SocketConnection.BeginRead(Int32 offset, Int32 size, TimeSpan timeout, Action1 callback, Object state) at System.ServiceModel.Channels.DelegatingConnection.BeginRead(Int32 offset, Int32 size, TimeSpan timeout, Action1 callback, Object state) at System.ServiceModel.Channels.ConnectionHelpers.IConnectionExtensions.ReadAsync(IConnection connection, Int32 offset, Int32 size, TimeSpan timeout) at System.ServiceModel.Channels.ConnectionHelpers.IConnectionExtensions.ReadAsync(IConnection connection, Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreambleAsync(IConnection connection, ArraySegment1 preamble, TimeSpan timeout) at System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnectionAsync(TimeSpan timeout) at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpenAsync(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.OnOpenAsyncInternal(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.System.ServiceModel.IAsyncCommunicationObject.OpenAsync(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.OpenAsyncInternal(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.Runtime.TaskHelpers.CallActionAsync[TArg](Action1 action, TArg argument) at System.ServiceModel.Channels.CommunicationObject.OpenOtherAsync(ICommunicationObject other, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.OnOpenAsync(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.OnOpenAsyncInternal(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.System.ServiceModel.IAsyncCommunicationObject.OpenAsync(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.OpenAsyncInternal(TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade) at System.ServiceModel.Channels.ServiceChannel.EnsureOpened(TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(MethodCall methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(MethodInfo targetMethod, Object[] args) --- End of stack trace from previous location where exception was thrown --- at System.Reflection.DispatchProxyGenerator.Invoke(Object[] args)}

Commonable answered 1/11, 2018 at 10:6 Comment(1)
NetCore Project also could invoke the service by adding the service reference via Microsoft WCF Web Service Reference Provider tool. Why not try it? and then based on the generated configuration file (reference.cs), we set up the binding configuration manually. learn.microsoft.com/en-us/dotnet/core/additional-tools/…Gleanings

© 2022 - 2024 — McMap. All rights reserved.