views:

523

answers:

4

I'm trying to host two WCF services in one application. I want them to share the same BaseAddress but have their own URLs something like: net.tcp://localhost:1234/service1 and net.tcp://localhost:1234/service2

The following config allows me to do that:

<system.serviceModel>
    <services>
        <service name="VanillaWcf.Shared.MyService" behaviorConfiguration="beh">
            <endpoint address="myservice" binding="netTcpBinding" name="tcpEndPoint" contract="VanillaWcf.Shared.IMyService" />
            <endpoint address="myservice" binding="wsHttpBinding" name="httpEndPoint" contract="VanillaWcf.Shared.IMyService"/>
            <host>
                <baseAddresses>
                    <add baseAddress="net.tcp://localhost:1234" />
                </baseAddresses>
            </host>
        </service>
        <service name="VanillaWcf.Shared.SecondService" behaviorConfiguration="beh">
            <endpoint address="secondService" binding="netTcpBinding" name="tcpEndPoint" contract="VanillaWcf.Shared.ISecondService"/>
            <endpoint address="secondService" binding="wsHttpBinding" name="httpEndPoint" contract="VanillaWcf.Shared.ISecondService"/>
            <host>
                <baseAddresses>
                    <add baseAddress="net.tcp://localhost:1234"/>
                </baseAddresses>
            </host>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="beh">
                <serviceMetadata httpGetEnabled="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

And the code is:

        ServiceHost host = new ServiceHost(typeof(MyService));
        ServiceHost secondHost = new ServiceHost(typeof(SecondService));

        host.Open();
        secondHost.Open();

This works fine.

However, I get an exception when I add http://localhost:4321 as the base address of both services in the config.

The exception is: The ChannelDispatcher at 'http://localhost:4321/' with contract(s) '"IHttpGetHelpPageAndMetadataContract"' is unable to open its IChannelListene' with an inner exception of A registration already exists for URI 'http://localhost:4321

I don't have any MEX configuration and I don't want it.

Note: My NetPortSharing service is disabled.

+1  A: 

You can't have two base address with the same scheme (net.tcp) and the same address - you'll have to change something.

One possibility might be to not use base addresses, but completely specify the net.tcp addresses on your two endpoints. This might work (should, because the whole address is different for the two services).

<service name="VanillaWcf.Shared.MyService" behaviorConfiguration="beh">
   <endpoint name="tcpEndPoint" 
       address="net.tcp://localhost:1234/myservice1" 
       binding="netTcpBinding" 
       contract="VanillaWcf.Shared.IMyService" />
</service>

Marc

marc_s
I don't. If you look at the config I have these addresses:net.tcp://localhost:1234/myservice and net.tcp://localhost:1234/secondservice and it works. The question is why it doesn't when I change net.tcp to Http and I guess it has something to do with IHttpGetHelpPageAndMetadataContract
Khash
I guess the trouble really is that you have the HTTP Get metadata behavior on both of these identical base addresses - so when you navigate to one of them, how should WCF know which service's meta data you want to see? You need to be using two separate base addresses, or change the metadata endpoints to something that's separate for the two endpoints (full URL for the MEX endpoints, which isn't identical)
marc_s
I'm sure I can see <serviceMetadata httpGetEnabled="false"/> in my question. Unless I am fully aware of how it works.
Khash
@Khash: just try to remove it and see - can you? Please? The httpGetEnabled just means the metadata cannot be retrieved using HTTP - but the service metadata is still being published on that address with the MEX protocol. Try removing the behaviorCOnfiguration from your service configurations - just to see....
marc_s
A: 

Port sharing is possible, but you need to configure things correctly.

See http://msdn.microsoft.com/en-us/library/ms734772.aspx

Steven Sudit
A: 

In general only one application can listen on a tcp port at a time.

For net.tcp MS has done some work to allow port sharing. See:

http://technet.microsoft.com/en-us/library/cc753154.aspx

But this is specific to the net.tcp binding. You therefore get a problem when you try to listen for http on the same port.

Shiraz Bhaiji
A: 

I found the answer, but can't figure out why! It turns out when using net.tcp the same base address can be used with different service addresses i.e. net.tcp://localhost:1234 as the base address and /service1 and /service2.

However, when using http the full URL should be specified at the service level: i.e. Leave base address blank and use http://localhost:4321/service1 and http://localhost:4321/service2 at the service level.

This seems a big inconsistent with the whole idea of decoupling protocol from configuration which WCF puts a lot of emphasis upon, but it seems to be the case.

Khash