0

I have a WinForms client application. I have the WCF server running on another computer as a part of a Windows Service that I wrote. I first tried NetPipeBinding and now NetTcpBinding. I did open up 2 ports in Windows Firewall with Advanced Security. The server OS is Windows Server 2016.

Here is the server code:

public Boolean CreatePipeServer(out string logEntry)
{
    try
    {
        NetTcpBinding ipcBinding = new NetTcpBinding()
        {
            Security = new NetTcpSecurity()
            {
                Mode = SecurityMode.None,
                Transport = new TcpTransportSecurity()
                {
                    ClientCredentialType = TcpClientCredentialType.None,
                    ProtectionLevel = System.Net.Security.ProtectionLevel.None,
                },
            },
            MaxBufferPoolSize = 6553600,
            MaxBufferSize = 6553600,
            MaxReceivedMessageSize = 6553600,
            MaxConnections = 1000,
            ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
            {
                MaxArrayLength = 2147483647,
                MaxBytesPerRead = 2147483647,
                MaxDepth = 2147483647,
                MaxNameTableCharCount = 2147483647,
                MaxStringContentLength = 2147483647,
            },
        };

        // Instantiate: Host Service
        Uri uriMex = new Uri("http://localhost:8000");
        this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService = new ServiceHost(typeof(IpcAppToService), uriMex);

        // Instantiate: Endpoint
        Uri uriService = new Uri("net.tcp://localhost:8004/StampIpcAppToService");
        this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.AddServiceEndpoint(typeof(StampIpc.IIpcAppToService), ipcBinding, uriService);

        // Instantiate: Service Meta Behavior
        ServiceMetadataBehavior ipcSmb = this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description.Behaviors.Find<ServiceMetadataBehavior>();
        if (null == ipcSmb)
        {
            ipcSmb = new ServiceMetadataBehavior()
            {
                HttpGetEnabled = true,
            };
            this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description.Behaviors.Add(ipcSmb);
            ServiceDescription serviceDescription = this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description;
        }

        // Instantiate: MEX Biding
        Binding ipcMexBinding = MetadataExchangeBindings.CreateMexHttpBinding();
        this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.AddServiceEndpoint(typeof(IMetadataExchange), ipcMexBinding, "MEX");

        // Capture events.
        ...

        // Start the service.
        this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Open();

        return true;
    }

    catch (Exception) { }

return false;
}

I am attempting to test a valid communication link by going to the Add > Service Reference... in Visual Studio 2019. No matter what I type, I keep receiving errors of one sort or the other. Currently, I placed:

net.tcp://10.10.70.134:8004/StampIpcAppToService

That throws the error:

The URI prefix is not recognized. Metadata contains a reference that cannot be resolved: 'net.tcp://10.10.70.134:8004/StampIpcAppToService'. Metadata contains a reference that cannot be resolved: 'net.tcp://10.10.70.134:8004/StampIpcAppToService'. If the service is defined in the current solution, try building the solution and adding the service reference again.

I already have the client code, but if I cannot get the Add Service Reference working, then the client code definitely will not work.

The code above starts as part of the OnStart event for the Windows Service.

What am I doing wrong?

UPDATE

The answer resolved the direct question above, however my real code uses code similar to the server side and I receive an error. I modified the code based on the answer and a bit of debugging. Current code is:

    public static Boolean ConnectToService()
    {
        ComAppToService.IsPipeAppToService = false;
        ComAppToService.IpcPipeFactory = null;
        Program.HostIpcAppToService = null;
        try
        {
            // Instantiate: Callack
            var ipcCallback = new IpcAppToServiceBack();
            InstanceContext ipcCallbackInstance = new InstanceContext(ipcCallback);

            // Instantiate: Endpoint
            Uri ipcUri = new Uri($"http://10.10.70.134:8000/mex");
            EndpointAddress ipcEndpoint = new EndpointAddress(ipcUri);

            // Instantiate: Binding
            // https://stackoverflow.com/questions/464707/maximum-array-length-quota
            WSDualHttpBinding ipcBindingHttp = new WSDualHttpBinding()
            {
                Security = new WSDualHttpSecurity() { Mode = WSDualHttpSecurityMode.None },
                MaxBufferPoolSize = 6553600,
                MaxReceivedMessageSize = 6553600,
                ClientBaseAddress = ipcUri,
                ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
                {
                    MaxArrayLength = 2147483647,
                    MaxBytesPerRead = 2147483647,
                    MaxDepth = 2147483647,
                    MaxNameTableCharCount = 2147483647,
                    MaxStringContentLength = 2147483647,
                },
            };

            // Instantiate: Factory
            ComAppToService.IpcPipeFactory = new DuplexChannelFactory<IIpcAppToService>(ipcCallbackInstance, ipcBindingHttp, ipcEndpoint);
            Program.HostIpcAppToService = ComAppToService.IpcPipeFactory.CreateChannel();

            // Open: Callback
            Program.HostIpcAppToService.OpenCallback(IpcCallbackDest.App);
            ComAppToService.IsPipeAppToService = true;

            return true;
        }

        catch (Exception ex)
        {
            // Log the exception.
            Debug.WriteLine(ex.Message);
        }

        return false;
    }

Exception:

InnerException = {"The message with Action 'http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions betwee...

UPDATE 2 (reflects updated answer)

Using NetTcpBinding generates this error:

Using URI:

Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8004");

Generates

Message = "There was no endpoint listening at net.tcp://jmr-engineering:8004/ that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details."

Using URI:

Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8000");

Generates

Message = "You have tried to create a channel to a service that does not support .Net Framing. It is possible that you are encountering an HTTP endpoint."

InnerException = {"Expected record type 'PreambleAck', found '72'."}

THE ANSWER:

The accepted answer needs a modification. Abraham did not have the correct URI, however he pointed me to SvcUtil.exe, which gave that to me.

URI:

net.tcp://10.10.70.134:8004/StampIpcAppToService

I do need NetTcpBinding, so the final client side code is:

    /// <summary>
    /// Connects the ipc application to service.
    /// </summary>
    /// <returns>Boolean.</returns>
    public static Boolean ConnectToService()
    {
        ComAppToService.IsPipeAppToService = false;
        ComAppToService.IpcPipeFactory = null;
        Program.HostIpcAppToService = null;
        try
        {
            // Instantiate: Callack
            var ipcCallback = new IpcAppToServiceBack();
            InstanceContext ipcCallbackInstance = new InstanceContext(ipcCallback);

            // Instantiate: Endpoint
            Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8004/StampIpcAppToService");
            EndpointAddress ipcEndpoint = new EndpointAddress(ipcUri);

            // Instantiate: Binding
            // https://stackoverflow.com/questions/464707/maximum-array-length-quota
            NetTcpBinding ipcBindingHttp = new NetTcpBinding()
            {
                Security = new NetTcpSecurity() { Mode = SecurityMode.None },
                MaxBufferPoolSize = 6553600,
                MaxReceivedMessageSize = 6553600,
                MaxBufferSize = 6553600,
                MaxConnections = 1000,
                ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
                {
                    MaxArrayLength = 2147483647,
                    MaxBytesPerRead = 2147483647,
                    MaxDepth = 2147483647,
                    MaxNameTableCharCount = 2147483647,
                    MaxStringContentLength = 2147483647,
                },
            };

            // Instantiate: Factory
            ComAppToService.IpcPipeFactory = new DuplexChannelFactory<IIpcAppToService>(ipcCallbackInstance, ipcBindingHttp, ipcEndpoint);
            Program.HostIpcAppToService = ComAppToService.IpcPipeFactory.CreateChannel();

            // Open: Callback
            Program.HostIpcAppToService.OpenCallback(IpcCallbackDest.App);
            ComAppToService.IsPipeAppToService = true;

            return true;
        }

        catch (Exception ex)
        {
            // Log the exception.
            Debug.WriteLine(ex.Message);
        }

        return false;
    }

Here is the output of the output.config from the SvcUtil.exe. The IpcAppToService.cs file was useless, but the config file was definitely helpful.

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <system.serviceModel>
        <bindings>
            <netTcpBinding>
            <binding name="NetTcpBinding_IIpcAppToService">
                <security mode="None" />
            </binding>
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="net.tcp://localhost:8004/StampIpcAppToService"
            binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IIpcAppToService"
            contract="IIpcAppToService" name="NetTcpBinding_IIpcAppToService" />
        </client>
        </system.serviceModel>
    </configuration>
Sarah Weinberger
  • 15,041
  • 25
  • 83
  • 130

1 Answers1

1

Adding service reference relies on the service metadata address instead of the service address. According to your above settings, the Uri in your Adding service reference dialog should be,

http://10.10.70.134:8000/mex

In general, we have to expose the metadata either by adding a Mex endpoint or by the HttpGetEnabled property of the ServiceMetedataBehavior. Subsequently, the client-side could generate a client proxy by using the SVCUtil tool.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
In Visual Studio, Adding Service reference dialog is a shortcut to generate a client proxy. It relies on the Mex service endpoint. The Mex endpoint address is necessary for the shortcut.
Feel free to let me know if there is anything I can help with.
Updated.
Duplex communication means we should use Nettcpbinding(supports duplex) on the client-side.

class Program
    {
        static void Main(string[] args)
        {
            NetTcpBinding binding = new NetTcpBinding()
            {
                Security = new NetTcpSecurity
                {
                    Mode = SecurityMode.None
                },
                MaxBufferPoolSize = 6553600,
                MaxBufferSize = 6553600,
                MaxReceivedMessageSize = 6553600,
                MaxConnections = 1000,
                ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
                {
                    MaxArrayLength = 2147483647,
                    MaxBytesPerRead = 2147483647,
                    MaxDepth = 2147483647,
                    MaxNameTableCharCount = 2147483647,
                    MaxStringContentLength = 2147483647,
                },
            };
            //replace it with your practical service address.
            Uri uri = new Uri("net.tcp://10.157.13.69:8004");
            ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri));
            IService service = factory.CreateChannel();
            var result = service.Test();
            Console.WriteLine(result);

        }

    }

    //the service contract shared between the client-side and the server-side.
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        string Test();

    }
Abraham Qian
  • 7,117
  • 1
  • 8
  • 22
  • The answer does resolve the direct question stated, but my code uses a client side counterpart to the server side code, not an Add-Service Reference, see client side code added to my question. I receive the exception stated. I modified the client side based on the answer and debugging. VS stated that I had to use `Dual` and not `Basic`. Still, I get an error. – Sarah Weinberger Jan 29 '20 at 06:07
  • @SarahWeinberger , please see the updated reply. we are supposed to keep the binding between the client-side and the server-side consistent when calling SOAP service, which guarantees the communication channel could be established. – Abraham Qian Jan 29 '20 at 08:04