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.
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();
}
}
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">