Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making WCF easier to configure

I have a set of WCF web services connected to dynamically by a desktop application.

My problem is the really detailed config settings that WCF requires to work. Getting SSL to work involves custom settings. Getting MTOM or anything else to work requires more. You want compression? Here we go again...

WCF is really powerful - you can use a host of different ways to connect, but all seem to involve lots of detailed config. If host and client don't match perfectly you get hard to decipher errors.

I want to make the desktop app far easier to configure - ideally some kind of auto-discovery. The users of the desktop app should just be able to enter the URL and it do the rest.

Does anyone know a good way to do this?

I know Visual Studio can set the config up for you, but I want the desktop app to be able to do it based on a wide variety of different server set-ups.

I know that VS's tools can be used externally, but I'm looking for users of the desktop apps to not have to be WCF experts. I know MS made this intentionally over complicated.

Is there any way, mechanism, 3rd party library or anything to make auto-discovery of WCF settings possible?

like image 230
Keith Avatar asked Sep 17 '08 20:09

Keith


2 Answers

Thanks, that was useful code (+1).

It's more than a little bit messy though, has some bugs (case sensitive checks that shouldn't be, for instance), has a load of UI functionality that I don't need and repeats a lot of code.

I've taken from it the actual discovery mechanism, re-wrote it and almost got it working (connects, but needs some finessing).

First some util functions used by the main method:

/// <summary>If the url doesn't end with a WSDL query string append it</summary>
static string AddWsdlQueryStringIfMissing( string input )
{
    return input.EndsWith( "?wsdl", StringComparison.OrdinalIgnoreCase ) ?
        input : input + "?wsdl";
}

/// <summary>Imports the meta data from the specified location</summary>
static ServiceEndpointCollection GetEndpoints( BindingElement bindingElement, Uri address, MetadataExchangeClientMode mode )
{
    CustomBinding binding = new CustomBinding( bindingElement );
    MetadataSet metadata = new MetadataExchangeClient( binding ).GetMetadata( address, mode );
    return new WsdlImporter( metadata ).ImportAllEndpoints();
}

Then a method that tries different way to connect and returns the endpoints:

public static ServiceEndpointCollection Discover( string url )
{
    Uri address = new Uri( url );
    ServiceEndpointCollection endpoints = null;

    if ( string.Equals( address.Scheme, "http", StringComparison.OrdinalIgnoreCase ) )
    {
        var httpBindingElement = new HttpTransportBindingElement();

        //Try the HTTP MEX Endpoint
        try { endpoints = GetEndpoints( httpBindingElement, address, MetadataExchangeClientMode.MetadataExchange ); }
        catch { }

        //Try over HTTP-GET
        if ( endpoints == null )
            endpoints = GetEndpoints( httpBindingElement,
                new Uri( AddWsdlQueryStringIfMissing( url ) ), MetadataExchangeClientMode.HttpGet );
    }
    else if ( string.Equals( address.Scheme, "https", StringComparison.OrdinalIgnoreCase ) )
    {
        var httpsBindingElement = new HttpsTransportBindingElement();

        //Try the HTTPS MEX Endpoint
        try { endpoints = GetEndpoints( httpsBindingElement, address, MetadataExchangeClientMode.MetadataExchange ); }
        catch { }

        //Try over HTTP-GET
        if ( endpoints == null )
            endpoints = GetEndpoints( httpsBindingElement,
                new Uri( AddWsdlQueryStringIfMissing( url ) ), MetadataExchangeClientMode.HttpGet );
    }
    else if ( string.Equals( address.Scheme, "net.tcp", StringComparison.OrdinalIgnoreCase ) )
        endpoints = GetEndpoints( new TcpTransportBindingElement(), 
            address, MetadataExchangeClientMode.MetadataExchange );

    else if ( string.Equals( address.Scheme, "net.pipe", StringComparison.OrdinalIgnoreCase ) )
        endpoints = GetEndpoints( new NamedPipeTransportBindingElement(), 
            address, MetadataExchangeClientMode.MetadataExchange );

    return endpoints;
}
like image 30
Keith Avatar answered Sep 24 '22 05:09

Keith


All information about the endpoint is available in metadata of a service, you can write a client what will explore the meta data of the service and will configure the client. For a code example you can look into this excellent Mex Explorer from Juval Lowy.

like image 147
MichaelT Avatar answered Sep 20 '22 05:09

MichaelT