18

Is it possible to host multiple service contracts in one WCF service? If so, how? I've been googling and some posts say you can do it (but not how) and others have said it's just not possible.

When I run the server, I get this error:

The contract name 'ConsoleAppWcfCommon.IBarService' could not be found in the list of contracts implemented by the service 'ConsoleAppWcfServer.FooService'.

This is my server code:

    static void Main(string[] args)
    {
        string serviceAddress = "net.tcp://localhost:8088/FooBarService";

        // I'm stuck here as I have to pick *one* service
        ServiceHost selfServiceHost = new ServiceHost(typeof(FooService));            

        // I can add both endpoints here, but this is what gives me the error.
        selfServiceHost.AddServiceEndpoint(typeof(IFooService), new NetTcpBinding(), serviceAddress);
        selfServiceHost.AddServiceEndpoint(typeof(IBarService), new NetTcpBinding(), serviceAddress);

        selfServiceHost.Open();
        Console.ReadLine();
        selfServiceHost.Close();
    }

And this is the client code:

    static void Main(string[] args)
    {
        NetTcpBinding netTcpBinding = new NetTcpBinding();

        EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:8088/FooBarService");

        // Call IFooService
        var channelFactoryFoo = new ChannelFactory<IFooService>(netTcpBinding, endpointAddress);
        IFooService channelFoo = channelFactoryFoo.CreateChannel();
        Debug.WriteLine(channelFoo.FooMethod1());

        // Call IBarService
        var channelFactoryBar = new ChannelFactory<IBarService>(netTcpBinding, endpointAddress);
        IBarService channelBar = channelFactoryBar.CreateChannel();
        Debug.WriteLine(channelBar.BarMethod1());
    }

My goal is to let the client make a call to Foo (or Bar) and only see the methods available to each. In my real application, I have about 10 domain entities with about four operations on each. I'm trying not to have one interface with 40 methods in it. And I don't want to have to host 10 different WCF services to do this.

6
  • 3
    The only way to do this is to have one service implementation class that implements both interfaces in question. Do you have that? So you would need to have public class FooService : IFooService, IBarService { .... } Commented May 11, 2013 at 21:02
  • 1
    stackoverflow.com/a/334554/352101 Commented May 11, 2013 at 21:03
  • @marc_s I don't have that, but I could as I own all of the code. In my example above, are you saying that the server code should work as-is if FooService implements both interfaces? Commented May 11, 2013 at 21:06
  • The other thing I'm not sure about is whether you can have two service endpoints at the same location, one for each of the service interfaces. But first of all, you'll definitely need one single service implementation class that implements both interfaces... Commented May 11, 2013 at 21:08
  • 2
    I got it working. I had to share a binding instance among the endpoints. I'll share the code as an answer so it can help someone else. Thanks, Marc. Commented May 11, 2013 at 21:11

1 Answer 1

29

As marc_s pointed out, the answer was to have one service implementation class that implements both interfaces. Below is the full working code.

Server:

    static void Main(string[] args)
    {
        string serviceAddress = "net.tcp://localhost:8088/FooBarService";

        ServiceHost selfServiceHost = new ServiceHost(typeof(FooService));            

        // The endpoints need to share this binding.
        var binding = new NetTcpBinding();

        selfServiceHost.AddServiceEndpoint(typeof(IFooService), binding, serviceAddress);
        selfServiceHost.AddServiceEndpoint(typeof(IBarService), binding, serviceAddress);

        selfServiceHost.Open();

        Console.WriteLine("The service is ready.");
        Console.WriteLine("Press any key to terminate service.");
        Console.WriteLine();
        Console.ReadKey();

        selfServiceHost.Close();
    }

Client:

    static void Main(string[] args)
    {
        NetTcpBinding netTcpBinding = new NetTcpBinding();

        EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:8088/FooBarService");

        // Call IFooService
        var channelFactoryFoo = new ChannelFactory<IFooService>(netTcpBinding, endpointAddress);
        IFooService channelFoo = channelFactoryFoo.CreateChannel();
        Console.WriteLine(channelFoo.FooMethod1());

        // Call IBarService
        var channelFactoryBar = new ChannelFactory<IBarService>(netTcpBinding, endpointAddress);
        IBarService channelBar = channelFactoryBar.CreateChannel();
        Console.WriteLine(channelBar.BarMethod1());

        Console.ReadKey();
    }

Foo Contract:

[ServiceContract]
public interface IFooService
{
    [OperationContract]
    string FooMethod1();

    [OperationContract]
    string FooMethod2();
}

Bar Contract:

[ServiceContract]
public interface IBarService
{
    [OperationContract]
    string BarMethod1();

    [OperationContract]
    string BarMethod2();
}

Foo Service:

public class FooService : IFooService, IBarService
{
    public string FooMethod1()
    {
        return "FooMethod1";
    }

    public string FooMethod2()
    {
        return "FooMethod2";
    }

    public string BarMethod1()
    {
        return "BarMethod1";
    }

    public string BarMethod2()
    {
        return "BarMethod2";
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

I really like that you posted your end result code - this does help others, me included. I see comments like I will post final code ; and yet people just don't do that and I am left banging my head! ++
Nice code, but if I am in WCF hosted on IIS, where do I put the stuff that goes in Main?
It would be in the area of your WCF service that initializes things when the service starts. Where do you currently set the bindings and endpoints? That's where this code would go.
In IIS hosted applications this must be set up using web.config, so the real answer is this code would go no-where.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.