Frage

Ich habe eine Reihe von WCF Web-Service von einer Desktop-Anwendung dynamisch verbunden.

Mein Problem ist, die wirklich detaillierten Konfigurationseinstellungen, die WCF zu arbeiten erfordert. Erste SSL Arbeit beinhaltet benutzerdefinierte Einstellungen. Erster MTOM oder irgendetwas anderes zu Arbeit erfordert mehr. Sie wollen Kompression? Hier gehen wir wieder ...

WCF ist wirklich mächtig - Sie eine Vielzahl von verschiedenen Arten verwenden zu verbinden, aber alle scheinen viele detaillierte Konfiguration einzubinden. Wenn Host und Client nicht perfekt passen Sie schwer zu bekommen, um Fehler zu entschlüsseln.

Ich mag die Desktop-Anwendung viel einfacher zu konfigurieren machen - im Idealfall eine Art von Auto-Discovery. Die Nutzer der Desktop-Anwendung sollten nur in der Lage sein, die URL eingeben und den Rest.

Kennt jemand eine gute Möglichkeit, dies zu tun?

Ich weiß, dass Visual Studio die Config-up für Sie einstellen können, aber ich möchte, dass die Desktop-App, um es auf einer Vielzahl von verschiedenen Server-Set-ups tun basiert.

Ich weiß, dass VS-Tools extern genutzt werden kann, aber ich bin für die Nutzer der Desktop-Anwendungen suchen, um nicht WCF Experten sein. Ich weiß, MS dies absichtlich über kompliziert gemacht.

Gibt es eine Möglichkeit, einen Mechanismus, 3rd-Party-Bibliothek oder irgendetwas zu automatischer Erkennung von WCF-Einstellungen möglich zu machen?

War es hilfreich?

Lösung

Alle Informationen über den Endpunkt ist in den Metadaten eines Service verfügbar sind, können Sie einen Client schreiben, was die Meta-Daten des Dienstes erforschen und wird den Client konfigurieren. Ein Codebeispiel können Sie diese hervorragende Mex Explorer von Juval Löwy.

Andere Tipps

Danke, das war nützlich Code (+1).

Es ist mehr als ein bisschen obwohl chaotisch, hat einige Bugs (case sensitive Kontrollen, die nicht sein, zum Beispiel sollen), hat eine Last von UI-Funktionalität, die ich nicht brauche und wiederholt eine Menge Code.

ich von dem tatsächlichen Entdeckung Mechanismus genommen habe, es wieder geschrieben und bekam fast daran zu arbeiten (eine Verbindung herstellt, aber einig finessing braucht).

Zunächst einige util Funktionen durch die Hauptmethode verwendet:

/// <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();
}

Dann wird eine Methode, die unterschiedliche Art und Weise versucht, zu verbinden und gibt die Endpunkte:

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;
}

Es gibt jetzt eine andere Art und Weise, dies zu tun, die nicht verfügbar war, als ich die ursprüngliche Frage gestellt. Microsoft unterstützt jetzt REST für WCF-Dienste.

  • Der Nachteil REST ist, dass Sie die WSDL verlieren.
  • Der Vorteil ist minimal config und WCF Vertrag Schnittstellen wird immer noch funktionieren!

Sie erhalten eine neue Referenz müssen System.ServiceModel.Web

Markieren Sie Ihre Operationen entweder mit WebInvoke oder WebGet

//get a user - note that this can be cached by IIS and proxies
[WebGet]
User GetUser(string id )

//post changes to a user
[WebInvoke]
void SaveUser(string id, User changes )

diese zu einer Website ist ganz einfach - eine .svc Datei hinzufügen:

<%@ServiceHost 
   Service="MyNamespace.MyServiceImplementationClass" 
   Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

Die Fabrik Zeile sagt ASP.net wie der Endpunkt aktivieren - Sie überhaupt keine Server-Seite Config benötigen

!

Konstruieren Sie dann Ihre ChannelFactory ziemlich unverändert, mit der Ausnahme, dass Sie einen Endpunkt nicht angeben müssen nicht mehr (oder Auto-entdecken Sie eine, wie ich in den anderen Antworten haben)

var cf = new WebChannelFactory<IMyContractInterface>();
var binding = new WebHttpBinding();

cf.Endpoint.Binding = binding;
cf.Endpoint.Address = new EndpointAddress(new Uri("mywebsite.com/myservice.svc"));
cf.Endpoint.Behaviors.Add(new WebHttpBehavior());

IMyContractInterface wcfClient = cf.CreateChannel();

var usr = wcfClient.GetUser("demouser");
// and so on...

Beachten Sie, dass ich nicht angegeben haben, oder die Client-Konfiguration entdeckt - es gibt keine lokale Konfiguration erforderlich

Ein weiterer großer Vorteil ist, dass Sie leicht zu JSON Serialisierung wechseln können -., Die die gleichen WCF-Dienste können von Java, Actionscript, Javascript, Silverlight oder irgendetwas anderes verbraucht werden, die JSON umgehen können und REST leicht

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top