2008-09-17 62 views
14

我有一組WCF Web服務通過桌面應用程序動態連接。使WCF更容易配置

我的問題是WCF需要工作的非常詳細的配置設置。讓SSL工作涉及到自定義設置。獲得MTOM或其他任何工作需要更多。你想壓縮?在這裏,我們再次...

WCF功能非常強大 - 您可以使用多種不同的方式進行連接,但都似乎涉及到大量的詳細配置。如果主機和客戶機不匹配,則很難解讀錯誤。

我想使桌面應用程序更容易配置 - 理想情況下某種自動發現。桌面應用程序的用戶應該只需輸入URL即可,剩下的工作就完成了。

有沒有人知道一個很好的方法來做到這一點?

我知道Visual Studio可以爲您設置配置,但是我希望桌面應用能夠基於各種不同的服務器設置進行配置。

我知道VS的工具可以在外部使用,但我在尋找桌面應用程序的用戶,不必是WCF專家。我知道MS故意讓這個過於複雜。

是否有任何方式,機制,第三方庫或任何可以自動發現WCF設置?

+0

「我知道MS故意讓這個過於複雜」[引用需要] – 2008-09-19 06:36:14

+0

也許這是不公平的。 MS有意使它成爲每一個你想改變的設置都可以,但是你需要一個WCF書籍和編程經驗來設置基礎知識。 – Keith 2008-09-19 12:17:08

回答

9

有關端點的所有信息都可以在服務的元數據中找到,您可以編寫一個客戶端,瀏覽服務的元數據並配置客戶端。對於代碼示例,您可以查看來自Juval Lowy的優秀Mex Explorer

1

謝謝,那是有用的代碼(+1)。

雖然它有點麻煩,但有一些錯誤(例如不應該是區分大小寫的檢查),有一些我不需要的UI功能,並重復了很多代碼。

我已經從中獲得了實際的發現機制,重新編寫了它,並且幾乎可以正常工作(連接,但需要一些修飾)。

首先由主法中使用的一些UTIL功能:

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

然後試圖不同的方式來連接和方法返回終點:

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

現在有另一種方式來做到這一點當我問原來的問題時,這是不可用的。微軟現在支持REST for WCF服務。

  • 使用REST的缺點是您失去了WSDL。
  • 好處是最小的配置和您的WCF合同接口仍然工作!

你需要一個新的參考System.ServiceModel.Web

標記您的操作有兩種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) 

添加這些到一個網站是很容易 - 添加.svc文件:

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

工廠行告訴ASP.net如何激活端點 - 根本不需要服務器端配置!

然後構建您的ChannelFactory是幾乎不變的,除非你不需要指定端點任何更多的(或自動發現一個,因爲我有其他的答案)

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

注意,我沒有指定或發現客戶端配置 - 沒有本地配置需要!

另一個很大的好處是,您可以輕鬆切換到JSON序列化 - 允許Java,ActionScript,Javascript,Silverlight或其他任何可以輕鬆處理JSON和REST的其他任何服務使用相同的WCF服務。