1

My WCF servers work like this: You subscribe to them by calling a service method, say Subscribe(). They send you results back on a callback channel, say MessageReceived(string message).

My issue right now is that I am only getting callback messages from one service endpoint, not both. In fact, just by debugging I see that my second service doesn't even get requests. Does anyone know what the problem is? Here is my code (note that I have two net.tcp addresses in the serviceAddresses string):

private void StartAggregatorHost(List<string> serviceAddresses)
{
        // Create a new service host for the routing service (note that RoutingService is a pre-defined Microsoft service model type which routes SOAP messages).
        aggregatorHost = new ServiceHost(typeof(RoutingService));

        // Set up the router address. A logger client will now connect to this address to get logged messages.
        string fqdn = System.Net.Dns.GetHostEntry("localhost").HostName;
        string routerAddress = string.Format("net.tcp://{0}:2099/LogAggregator", fqdn);

        // Set up our router binding.
        NetTcpBinding routerBinding = new NetTcpBinding(SecurityMode.None, true);
        routerBinding.SendTimeout = new TimeSpan(0, 1, 0);       
        routerBinding.ReceiveTimeout = new TimeSpan(25, 0, 0);
        routerBinding.MaxReceivedMessageSize = int.MaxValue;
        routerBinding.MaxConnections = int.MaxValue;
        routerBinding.ListenBacklog = int.MaxValue;
        routerBinding.ReliableSession.Enabled = true;
        routerBinding.ReliableSession.Ordered = true;
        routerBinding.ReliableSession.InactivityTimeout = new TimeSpan(15, 0, 0, 0);

        // Define the type of router in use. For duplex sessions like in our case, we want to use the IDuplexSessionRouter.
        Type contractType = typeof(IDuplexSessionRouter);

        // Add the endpoint that the router will use to recieve and relay messages. Note the use of System.ServiceModel.Routing.IDuplexSessionRouter.
        aggregatorHost.AddServiceEndpoint(contractType, routerBinding, routerAddress);

        // Create the endpoint list that contains the service endpoints we want to route to.
        List<ServiceEndpoint> endpointList = new List<ServiceEndpoint>();

        foreach (string serverAddress in serviceAddresses)
        {
            // Set up our server binding(s) for each server.
            NetTcpBinding serverBinding = new NetTcpBinding(SecurityMode.None, true);
            serverBinding.SendTimeout = new TimeSpan(0, 1, 0);
            serverBinding.ReceiveTimeout = new TimeSpan(25, 0, 0);
            serverBinding.MaxReceivedMessageSize = int.MaxValue;
            serverBinding.MaxConnections = 1;
            serverBinding.ListenBacklog = int.MaxValue;
            serverBinding.ReliableSession.Enabled = true;
            serverBinding.ReliableSession.Ordered = true;
            serverBinding.ReliableSession.InactivityTimeout = new TimeSpan(15, 0, 0, 0);

            // Create the server endpoint the router will route messages to and from.
            ContractDescription contract = ContractDescription.GetContract(contractType);
            ServiceEndpoint server = new ServiceEndpoint(contract, serverBinding, new EndpointAddress(serverAddress));

            // Add the server to the list of endpoints.
            endpointList.Add(server);
        }

        // Create a new routing configuration object.
        RoutingConfiguration routingConfiguration = new RoutingConfiguration();

        // Add a MatchAll filter to the Router's filter table. Map it to the endpoint list defined earlier. When a message matches this filter, it will be sent to the endpoint contained in the list.
        routingConfiguration.FilterTable.Add(new MatchAllMessageFilter(), endpointList);

        // Attach the behavior to the service host.
        aggregatorHost.Description.Behaviors.Add(new RoutingBehavior(routingConfiguration));

        // Open the service host.
        aggregatorHost.Open();



        m_eventLog.WriteEntry(string.Format("Log aggregator service hosted at {0}.", routerAddress), EventLogEntryType.Information);

}

So once again...this is what I want:

CLIENT ---REQ---> ROUTER ---REQ---> SVC1
                         ---REQ---> SVC2

CLIENT <---CALLBACK1--- ROUTER <---CALLBACK1--- SVC1
       <---CALLBACK2---        <---CALLBACK2--- SVC2

This is what I'm getting (even though I added the second service to my router it seems it doesn't even call its service methods):

CLIENT ---REQ---> ROUTER ---REQ---> SVC1

CLIENT <---CALLBACK--- ROUTER <---CALLBACK--- SVC1
Alexandru
  • 12,264
  • 17
  • 113
  • 208
  • 1
    A few things you could check: - Do SVC1 and SVC2 run correctly when you try to call them manually? - Try to add service endpoints one by one instead of adding the List - Try to specify a priority when adding to the FilterTable (same priority for both SVC1 & SVC2) - Try to use an XML routing configuration file first and as soon as it's working switch to code – MaxSC Jul 01 '13 at 08:55
  • @MaxS-Betclic - Post this as an answer RIGHT NOW, you hero. It was the priority that I was missing. I guess that passing in a list automatically generates priorities, so you need to add in each service individually and specify its priority: routingConfiguration.FilterTable.Add(new MatchAllMessageFilter(), new List { yourService }, 1); – Alexandru Jul 02 '13 at 14:40
  • I broke Rule #1 in programming: Don't assume anything works the way it should. – Alexandru Jul 02 '13 at 14:46

1 Answers1

1

You should set a specific priority adding SVC1 & SVC2 to the FilterTable.

routingConfiguration.FilterTable.Add(new MatchAllMessageFilter(), new List<YourServiceType> { yourService }, 1);

Further info here.

MaxSC
  • 4,698
  • 2
  • 23
  • 36