Search code examples
wcfwcf-binding

net.tcp works when programmatically set, but not when using config file


I'm trying to switch from programmatically setting the endpoint to using the config file. The problem is that when I use the config file, there is no error thrown, but the tcp port is not opened, and clients cannot connect.

This is netstat showing the port being opened when programmatically set, and then with the config file. netstat output

The following is my complete example client server and contracts app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>   
        <services>
            <service name="Server.CustomerService">
                <endpoint 
                    address="net.tcp://localhost:8081/CustomerService"
                    binding="netTcpBinding"
                    contract="Shared.ICustomerService"/>
            </service>
        </services>
    </system.serviceModel>
</configuration>

Server:

class ProgramService
    {
        static List<Customer> _customers = new List<Customer>();
        static void Main(string[] args)
        {
            CreateCustomers();
            Uri netTCPObject = new Uri("net.tcp://localhost:8081/CustomerService");
            ServiceHost sessionHost = new ServiceHost(typeof(CustomerService), netTCPObject);
            //ServiceHost sessionHost = new ServiceHost("Server.CustomerService");  //using the app.config

            sessionHost.Open();

            Console.WriteLine("Service is running");
            Console.ReadLine();
            sessionHost.Close();
        }

        private static void CreateCustomers()
        {
            _customers.Add(new Customer() { CustomerId = 1, FirstName = "Fred", LastName = "Flintstone" });
            _customers.Add(new Customer() { CustomerId = 2, FirstName = "John", LastName = "Doe" });
            _customers.Add(new Customer() { CustomerId = 3, FirstName = "Rebecca", LastName = "Johndaughter" });
            _customers.Add(new Customer() { CustomerId = 4, FirstName = "Julie", LastName = "Herald" });
        }

        public class CustomerService : ICustomerService
        {
            public Customer GetCustomer(int customerId)
            {
                return _customers.FirstOrDefault(c => c.CustomerId == customerId);
            }

            public bool UpdateCustomer(Customer customer)
            {
                var curCust = _customers.FirstOrDefault(c => c.CustomerId == customer.CustomerId);
                if (curCust != null)
                {
                    curCust.FirstName = customer.FirstName;
                    curCust.LastName = customer.LastName;
                }
                else
                {
                    _customers.Add(customer);
                }
                return true;
            }
        }
    }

Contracts:

namespace Shared
{
    [ServiceContract()]
    public interface ICustomerService
    {
        [OperationContract]
        Customer GetCustomer(int customerId);

        [OperationContract]
        bool UpdateCustomer(Customer customer);
    }

    [DataContract]
    public class Customer
    {
        [DataMember]
        public string FirstName { get; set; }

        [DataMember]
        public string LastName { get; set; }

        [DataMember]
        public int CustomerId { get; set; }
    }
}

Client:

class ProgramClient
{
    static void Main(string[] args)
    {
        //http://stackoverflow.com/a/2943206/232226
        NetTcpBinding binding = new NetTcpBinding();
        EndpointAddress endpoint = new EndpointAddress("net.tcp://localhost:8081/CustomerService");
        ChannelFactory<ICustomerService> factory =  new ChannelFactory<ICustomerService>(binding, endpoint);

        ICustomerService service = factory.CreateChannel();
        for (int i = 1; i < 5; i++)
        {
            Customer customer = service.GetCustomer(i);
            Console.WriteLine(String.Format("  Customer {0} {1} received.", customer.FirstName, customer.LastName));
        }
        Console.ReadLine();
    }
}

Solution

  • The ServiceHost constructor has an overload accepting a Type and one accepting an object, either being a type or an instance of a service class.

    This means that new ServiceHost("someString") will call the object overload, which is going to throw an exception because string does not implement a service.

    You need to call it with your service type:

    var serviceHost = new ServiceHost(typeof(CustomerService))
    

    And in configuration, use the full name of the type:

    <service name="ServiceNamespace.ProgramService.CustomerService">