Share via


Using MetadataResolver to dynamically swap endpoints for a given contract

I've been having a lot of fun recently thinking about how clients can fail to connect to one endpoint and recover to find any other endpoint for that contract that a service supports. The MetadataResolver class makes it real easy, at least, I think so. See what you think:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Design;
using WebServices = System.Web.Services.Description;

public class Client
{
public static void Main()
{
// Client has an endpoint for metadata
EndpointAddress mexAddress
= new EndpointAddress(new Uri("https://localhost:8082/ServiceMetadata/mex"));
EndpointAddress httpGetAddress
= new EndpointAddress(new Uri("https://localhost:8082/ServiceMetadata?wsdl"));

    // Section 1.
// Create a proxy to the service you want to use
FirstServiceProxy proxy = new FirstServiceProxy("IFirstService");

    // Get the endpoints for such a service
MetadataResolver resolver = new MetadataResolver(mexAddress);
ServiceEndpointCollection endpoints = resolver.RetrieveEndpoints();
ServiceEndpoint newEndpoint = null;
Console.WriteLine("Trying all available WS-MEX endpoints...");

foreach(ServiceEndpoint point in endpoints)
{
if (point != null)
{
newEndpoint = point;
proxy.Endpoint.Address = newEndpoint.Address;
proxy.Endpoint.Binding = newEndpoint.Binding;
Console.WriteLine(
proxy.HelloFirst("Client used the "
+ point.Address.ToString()
+ " address.")
);
}
}
proxy.Close();
// Section 2.
// Get the endpoints for such a service using Http/Get request
resolver = new MetadataResolver(httpGetAddress);
endpoints = resolver.RetrieveEndpointsUsingHttpGet();
newEndpoint = null;
IFirstService serviceChannel;
Console.WriteLine(
"\r\nTrying all endpoints from HTTP/Get and with direct service channels...");
foreach(ServiceEndpoint point in endpoints)
{
if (point != null)
{
newEndpoint = point;
ChannelFactory<IFirstService> factory = new ChannelFactory<IFirstService>(
newEndpoint.Binding,
newEndpoint.Address
);

        serviceChannel = factory.CreateChannel();
Console.WriteLine(
serviceChannel.HelloFirst("Client used the "
+ point.Address.ToString()
+ " address.")
);
}
}
// Section 3.
// Get other information.

    Console.WriteLine("URI of the metadata documents retreived:");
Collection<MetadataDocument> otherDocs = resolver.ResolvedMetadata;
foreach(MetadataDocument doc in otherDocs)
Console.WriteLine(doc.Dialect + " : " + doc.Identifier);

  }
}