Использование службы WCF из веб-приложения .net core 2.1 - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть приложение .net Framework, которое успешно использует службу WCF, и когда я пытаюсь скопировать настройки в мою библиотеку классов .net standard 2.0, которая используется веб-приложением .net core 2.1, я получаю различные ошибки. в зависимости от того, как я его настроил.

Во-первых, это рабочая потребительская конфигурация:

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

Сценарий 1: Попытайтесь дублировать настройки настолько, насколько я мог:

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

Получение исключения для этой строки: security.Message.ClientCredentialType = MessageCredentialType.Certificate; Исключение:

{System.PlatformNotSupportedException: MessageSecurityOverTcp.ClientCredentialType не поддерживается для значений, отличных от «MessageCredentialType.None». в System.ServiceModel.MessageSecurityOverTcp.set_ClientCredentialType (значение MessageCredentialType)


Сценарий 2: изменен тип MessageCrendentialType на 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);
        }
    }

Получение исключения по: this.ChannelFactory.Open();. Если я пропущу эту строку, я получу исключение: base.Channel.InvokeRACService(message); Исключение:

{System.PlatformNotSupportedException: NetTcpBinding.CreateMessageSecurity не поддерживается. в System.ServiceModel.NetTcpBinding.CreateMessageSecurity () в System.ServiceModel.NetTcpBinding.CreateBindingElements () в System.ServiceModel.Channels.Binding.EnsureInvariants (String contractName) в System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory (ServiceEndpoint serviceEndpoint, логическое значение useActiveAutoClose) в System.ServiceModel.ChannelFactory.OnOpening () в System.ServiceModel.Channels.CommunicationObject.System.ServiceModel.IAsyncCommunicationObject.OpenAsync (TimeSpan timeout) в System.ServiceModel.Channels.CommunicationObject.OpenAsyncInternal (время ожидания TimeSpan) в System.ServiceModel.ChannelFactory.EnsureOpened () в System.ServiceModel.DuplexChannelFactory1.CreateChannel (InstanceContext callbackInstance, адрес EndpointAddress, Uri через) at System.ServiceModel.ClientBase1.get_Channel ()}


Сценарий 3: изменение режима безопасности: security.Mode = SecurityMode.None; (в методе CreateNetTcpBinding)

Получение исключения при вызове услуги base.Channel.InvokeService(message); Исключение:

{System.ServiceModel.CommunicationException: соединение с сокетом было прервано. Это может быть вызвано ошибкой обработки вашего сообщения или превышением тайм-аута приема удаленным хостом, или проблемой основного сетевого ресурса. Тайм-аут локального сокета был '00: 09: 59.8599605 '. ---> System.Net.Sockets.SocketException: существующее соединение было принудительно закрыто удаленным хостом в System.ServiceModel.Channels.SocketConnection.HandleReceiveAsyncCompleted () в System.ServiceModel.Channels.SocketConnection.BeginReadCore (смещение Int32, размер Int32, время ожидания TimeSpan, обратный вызов Action 1 callback, Object state) --- End of inner exception stack trace --- at System.ServiceModel.Channels.SocketConnection.BeginReadCore(Int32 offset, Int32 size, TimeSpan timeout, Action 1, состояние объекта) в System.ServiceModel.Channels.SocketConnection.BeginRead (смещение Int32, размер Int32, время ожидания TimeSpan, обратный вызов Action 1 callback, Object state) at System.ServiceModel.Channels.DelegatingConnection.BeginRead(Int32 offset, Int32 size, TimeSpan timeout, Action 1, состояние объекта) в System.ServiceModel.Channels.ConnectionHelpers.IConnectionExtensions.ReadAsync (соединение IConnection, смещение Int32, размер Int32, время ожидания TimeSpan) в System.ServiceModel.Channels.ConnectionHelpers.IConnectionExtensions.ReadAsync (соединение IConnection, буфер Byte [], смещение Int32, размер Int32, время ожидания TimeSpan) в System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreambleAsync (соединение IConnection, действие ArraySegment 1 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](Action 1, аргумент TArg) в System.ServiceModel.Channels.CommunicationObject.OpenOtherAsync (ICommunicationObject other, TimeSpan timeout) в System.ServiceModel.Channels.ServiceChannel.OnOpenAsync (время ожидания TimeSpan) в System.ServiceModel.Channels.CommunicationObject.OnOpenAsyncInternal (время ожидания TimeSpan) в System.ServiceModel.Channels.CommunicationObject.System.ServiceModel.IAsyncCommunicationObject.OpenAsync (TimeSpan timeout)в System.ServiceModel.Channels.CommunicationObject.OpenAsyncInternal (время ожидания TimeSpan) в System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call (канал ServiceChannel, тайм-аут TimeSpan) в System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce (время ожидания, каскад CallOnceManager) в System.ServiceModel.Channels.ServiceChannel.EnsureOpened (TimeSpan timeout) в System.ServiceModel.Channels.ServiceChannel.Call (строковое действие, логический односторонний режим, операция ProxyOperationRuntime, Object [] ins, Object [] outs, TimeSpan timeout) в System.ServiceModel.Channels.ServiceChannelProxy.InvokeService (MethodCall methodCall, операция ProxyOperationRuntime) в System.ServiceModel.Channels.ServiceChannelProxy.Invoke (MethodInfo targetMethod, Object [] args) --- Конец стека трассировки от предыдущего местоположения, где было сгенерировано исключение --- в System.Reflection.DispatchProxyGenerator.Invoke (Object [] args)}

...