2008-09-17 14 views
14

Tengo un conjunto de servicios web WCF conectados dinámicamente por una aplicación de escritorio.Haciendo que WCF sea más fácil de configurar

Mi problema es la configuración de configuración realmente detallada que WCF requiere para funcionar. Hacer que SSL funcione implica una configuración personalizada. Hacer que MTOM o cualquier otra cosa funcione requiere más. ¿Quieres compresión? Aquí vamos de nuevo ...

WCF es realmente potente: puede utilizar una gran cantidad de formas diferentes de conectarse, pero todas parecen implicar muchas configuraciones detalladas. Si el host y el cliente no coinciden perfectamente, es difícil descifrar los errores.

Quiero hacer que la aplicación de escritorio sea mucho más fácil de configurar, idealmente algún tipo de descubrimiento automático. Los usuarios de la aplicación de escritorio solo deberían poder ingresar la URL y el resto.

¿Alguien sabe una buena manera de hacer esto?

Sé que Visual Studio puede configurar la configuración por usted, pero quiero que la aplicación de escritorio pueda hacerlo en base a una amplia variedad de diferentes configuraciones de servidor.

Sé que las herramientas de VS se pueden usar externamente, pero estoy buscando usuarios de las aplicaciones de escritorio para que no tengan que ser expertos de WCF. Sé que MS hizo esto intencionalmente más complicado.

¿Hay alguna manera, mecanismo, biblioteca de terceros o algo para hacer posible el descubrimiento automático de la configuración de WCF?

+0

"Sé que MS hizo esto intencionalmente demasiado complicado" [citación necesitada] –

+0

Quizás eso es injusto. MS lo hizo intencionalmente para que cada configuración que pudieras cambiar pudiera ser, pero que necesitarías un libro de WCF y experiencia en programación para configurar lo básico. – Keith

Respuesta

9

Toda la información sobre el punto final está disponible en los metadatos de un servicio, puede escribirle a un cliente qué explorará los metadatos del servicio y configurará el cliente. Para un ejemplo de código, puede consultar este excelente Mex Explorer de Juval Lowy.

1

Gracias, ese fue el código útil (+1).

Sin embargo, es más que un poco complicado, tiene algunos errores (por ejemplo, las comprobaciones sensibles a mayúsculas y minúsculas que no deberían ser), tiene una carga de funcionalidad de IU que no necesito y repite una gran cantidad de código.

He tomado de él el mecanismo de descubrimiento real, lo reescribí y casi lo hago funcionar (se conecta, pero necesita algunas finessing).

En primer lugar algunas funciones util utilizados por el método principal:

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

A continuación, un método que intenta diferente manera de conectar y devuelve los puntos finales:

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

ahora hay otra manera de hacer esto eso no estaba disponible cuando hice la pregunta original. Microsoft ahora es compatible con REST para servicios WCF.

  • La desventaja de utilizar REST es que pierde el WSDL.
  • ¡La ventaja es la configuración mínima y las interfaces de contrato de WCF seguirán funcionando!

Usted necesitará una nueva referencia a System.ServiceModel.Web

Marque sus operaciones, ya sea con o WebInvokeWebGet

//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) 

Adición de éstos a un sitio es fácil - añadir un archivo .svc:

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

La línea de fábrica le dice a ASP.net cómo activar el punto final - ¡no necesita configuración del servidor en absoluto!

A continuación, la construcción de su ChannelFactory es más o menos sin cambios, excepto que no es necesario especificar un punto final más (o auto-descubrir uno como lo he hecho en las otras respuestas)

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... 

en cuenta que yo no se ha especificado o no se ha descubierto la configuración del cliente; no se necesita configuración local.

Otra gran ventaja es que puede cambiar fácilmente a la serialización JSON, que permite que los mismos servicios WCF sean consumidos por Java, ActionScript, Javascript, Silverlight o cualquier otra cosa que pueda manejar JSON y REST fácilmente.

+0

También he blogueado sobre por qué esto ha cambiado: http://bizvprog.blogspot.com/2009/11/giving-up-on-soap-for-good.html – Keith

Cuestiones relacionadas