wcfnettcpbindingwindows-hosting

Add service reference when using netTcp binding


I have a WCF service that I tested by copying its interfaces to a sample client project.
Now I want to work properly by adding a service reference.
The service is hosted in windows hosting (using installUtil).
The service has 2 projects - externals (interfaces + datacontracts) and internals (implementations).
For some reason it didn't have an app.config so I added one manually:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="ExecutionService" behaviorConfiguration="Default">
        <endpoint name="TCPEndpoint" address="" binding ="netTcpBinding" contract="Externals.IExecutionService"/>
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:3040/ExecutionService"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Default">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Trying to add a service reference from my sample client causes the following error:

Metadata contains a reference that cannot be resolved: 'net.tcp://localhost:3040/ExecutionService/Externals.IExecutionService'.
There was no endpoint listening at net.tcp://localhost:3040/ExecutionService/Externals.IExecutionService that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
If the service is defined in the current solution, try building the solution and adding the service reference again.

I saw here that there's no need in app.config.
I'm a bit confused and I'm a beginner with WCF.
How can a nice WPF app reference my service? I want the service to be windows hosted and I don't want to drag dlls with me.

Edit
I added a metadata endpoint and my appconfig now looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="ExecutionService" behaviorConfiguration="Default">
        <endpoint name="TCPEndpoint" 
                  address="" 
                  binding ="netTcpBinding" 
                  contract="Externals.IExecutionService"/>
        <endpoint address="mex" 
                  binding="maxHttpBinding" 
                  contract="Externals.IExecutionService"/>
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:3040/ExecutionService"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Default">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

I tried adding a service reference by using net.tcp://localhost:3040/ExecutionService, net.tcp://localhost:3040/ExecutionService/Externals and net.tcp://localhost:3040/ExecutionService/Externals/IExecutionService and I'm still getting the same error.


Solution

  • You need to do:

    1. maxHttpBinding -> mexTcpBinding - you cannot use mexHttpBinding on net.tcp endpoint (and it's mex not max)
    2. the contract for mex endpoint must be IMetadataExchange - as you want to have service metadata available through this endpoint
    3. httpGetEnabled="false" as there will be no http endpoint to get metadata from
    4. When I was testing the solution in a simple console host I needed to change name in <service> tag to Externals.ExecutionService (but this depends on how you instantiate the service)

    Then your service reference will be available at: net.tcp://localhost:3040/ExecutionService/mex as base address is net.tcp://localhost:3040/ExecutionService and the relative address for the mex endpoint is set to mex

    Final app.config is below:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    <system.serviceModel>
    <services>
      <service name="Externals.ExecutionService" behaviorConfiguration="Default">
        <endpoint name="TCPEndpoint"
                  address=""
                  binding ="netTcpBinding"
                  contract="Externals.IExecutionService"/>
        <endpoint address="mex"
                  binding="mexTcpBinding"
                  contract="IMetadataExchange"/>
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:3040/ExecutionService"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Default">
          <serviceMetadata httpGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    </system.serviceModel>
    </configuration>
    

    For a quick test if the configuration is correct I used console host app as a service host. Program.cs:

    using System;
    using System.ServiceModel;
    
    namespace Externals
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                var sh=new ServiceHost(typeof(ExecutionService));
                sh.Open();
                Console.WriteLine("Service running press any key to terminate...");
                Console.ReadKey();
                sh.Close();
            }
        }
    }
    

    Run the console app and try to add service reference to your project through net.tcp://localhost:3040/ExecutionService/mex.