Question

How to set fall-back endpoint. I'm having more than one endpoint specified in the conifg file like follows. If the service was not accessible, then my client should check the next address specified in the list.

Client Configuration File:

<client>
  <endpoint address="http://192.168.1.4/SampleAppWeb/Services/SampleAppService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISampleAppService"
        contract="SampleAppServiceReference.ISampleAppService" name="BasicHttpBinding_ISampleAppService" />
  <endpoint address="http://172.168.12.121/SampleAppWeb/Services/SampleAppService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISampleAppService"
        contract="SampleAppServiceReference.ISampleAppService" name="BasicHttpBinding_ISampleAppService1" />
  <endpoint address="http://127.0.0.1/Services/SampleAppWeb/SampleAppService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISampleAppService"
        contract="SampleAppServiceReference.ISampleAppService" name="BasicHttpBinding_ISampleAppService2" />
  <endpoint address="http://172.168.111.115/Services/SampleAppWeb/SampleAppService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISampleAppService"
        contract="SampleAppServiceReference.ISampleAppService" name="BasicHttpBinding_ISampleAppService3" />          
</client>

Code Behind:

var pass = new SampleAppServiceReference.SampleAppServiceClient("BasicHttpBinding_ISampleAppService3");
Was it helpful?

Solution

WCF itself doesn't have any built-in feature for this, but you can easily create a class which will do the retrying for you. The example below shows one such way. Notice that if your binding uses session, you may need to recreate the client (instead of simply reusing it), as its channel will likely be faulted if an error happens.

public class StackOverflow_4968244
{
    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        int Add(int x, int y);
    }
    public class Service : ITest
    {
        public int Add(int x, int y)
        {
            Console.WriteLine("Request at service: {0}", OperationContext.Current.Host.BaseAddresses[0]);
            if (new Random().Next(3) == 0)
            {
                throw new InvalidOperationException("Random error");
            }

            return x + y;
        }
    }
    public class Client : ClientBase<ITest>, ITest
    {
        public Client(string address) : base(new BasicHttpBinding(), new EndpointAddress(address)) { }

        public int Add(int x, int y)
        {
            return this.Channel.Add(x, y);
        }
    }
    public class SafeClient : ITest
    {
        List<Client> clients;
        public SafeClient(params Client[] clients)
        {
            this.clients = new List<Client>(clients);
        }

        public int Add(int x, int y)
        {
            foreach (var client in this.clients)
            {
                try
                {
                    return client.Add(x, y);
                }
                catch (CommunicationException)
                {
                    Console.WriteLine("Error calling client {0}, retrying with next one", client.Endpoint.Address.Uri);
                }
            }

            throw new InvalidOperationException("All services seem to be down");
        }
    }

    public static void Test()
    {
        string baseAddress1 = "http://" + Environment.MachineName + ":8000/Service";
        string baseAddress2 = "http://" + Environment.MachineName + ":8001/Service";
        string baseAddress3 = "http://" + Environment.MachineName + ":8002/Service";
        ServiceHost host1 = new ServiceHost(typeof(Service), new Uri(baseAddress1));
        ServiceHost host2 = new ServiceHost(typeof(Service), new Uri(baseAddress2));
        ServiceHost host3 = new ServiceHost(typeof(Service), new Uri(baseAddress3));
        host1.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
        host2.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
        host3.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
        host1.Open();
        host2.Open();
        host3.Open();
        Console.WriteLine("Hosts opened");

        SafeClient safeClient = new SafeClient(
            new Client(baseAddress1),
            new Client(baseAddress2),
            new Client(baseAddress3));
        for (int i = 0; i < 20; i++)
        {
            Console.WriteLine(safeClient.Add(i, 10));
        }

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host1.Close();
        host2.Close();
        host3.Close();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top