Customizing a Metadata Resolver

I'm trying to use a metadata resolver but the metadata endpoint requires a custom binding. How do I override the binding used by MetadataResolver?

The overloads on MetadataResolver are pretty strange, but you can pick any of the ones that take an instance of MetadataExchangeClient.

 public static IAsyncResult BeginResolve(IEnumerable<ContractDescription> contracts, EndpointAddress address, MetadataExchangeClient client, AsyncCallback callback, object asyncState);
public static IAsyncResult BeginResolve(IEnumerable<ContractDescription> contracts, Uri address, MetadataExchangeClientMode mode, MetadataExchangeClient client, AsyncCallback callback, object asyncState);
public static ServiceEndpointCollection Resolve(IEnumerable<ContractDescription> contracts, EndpointAddress address, MetadataExchangeClient client);
public static ServiceEndpointCollection Resolve(IEnumerable<ContractDescription> contracts, Uri address, MetadataExchangeClientMode mode, MetadataExchangeClient client);

Let's take the following ServiceHost as an example. It uses BasicHttpBinding for metadata exchange instead of one of the normal metadata endpoint bindings.

 ServiceHost host = new ServiceHost(typeof(Service), new Uri("localhost:8080"));
host.AddServiceEndpoint(typeof(IService), new WSHttpBinding(), "servicedir/service");
host.Description.Behaviors.Add(new ServiceMetadataBehavior());
host.AddServiceEndpoint(typeof(IMetadataExchange), new BasicHttpBinding(), "mex");
host.Open();

Now, let's look at some code using MetadataResolver against this endpoint. We'll need to create a collection of contracts that includes IService. Also, we'll need to match the address and binding from the earlier service description.

 EndpointAddress address = new EndpointAddress("localhost:8080/mex");
MetadataExchangeClient client = new MetadataExchangeClient(new BasicHttpBinding());
List<ContractDescription> contracts = new List<ContractDescription>();
contracts.Add(ContractDescription.GetContract(typeof(IService)));
ServiceEndpointCollection endpoints = MetadataResolver.Resolve(contracts, address, client);

Console.WriteLine(endpoints[0].Address);
Console.WriteLine(endpoints[0].Binding);
Console.WriteLine(endpoints[0].Contract.Name);

You can run this to see what the metadata resolver is getting back from the endpoint.

Next time: Restarting a Failed Service