Dot-Net

使 WCF 更易於配置

  • December 3, 2009

我有一組由桌面應用程序動態連接的 WCF Web 服務。

我的問題是 WCF 需要工作的非常詳細的配置設置。讓 SSL 工作涉及自定義設置。讓 MTOM 或其他任何東西工作需要更多。你要壓縮嗎?我們重新來過吧…

WCF 真的很強大——你可以使用許多不同的方式來連接,但似乎都涉及到很多詳細的配置。如果主機和客戶端不完全匹配,您將很難破譯錯誤。

我想讓桌面應用程序更容易配置——最好是某種自動發現。桌面應用程序的使用者應該能夠輸入 URL,然後它會完成其餘的工作。

有誰知道這樣做的好方法?

我知道 Visual Studio 可以為您設置配置,但我希望桌面應用程序能夠基於各種不同的伺服器設置來完成。

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

是否有任何方法、機制、第 3 方庫或任何東西可以自動發現 WCF 設置?

有關端點的所有資訊都在服務的元數據中可用,您可以編寫客戶端來探索服務的元數據並配置客戶端。對於程式碼範例,您可以查看來自 Juval Lowy 的這個出色的Mex Explorer 。

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

不過,它有點混亂,有一些錯誤(例如,不應該進行區分大小寫的檢查),有很​​多我不需要的 UI 功能,並且重複了很多程式碼。

我從中獲取了實際的發現機制,重新編寫了它並幾乎讓它工作(連接,但需要一些技巧)。

首先是 main 方法使用的一些 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;
}

引用自:https://stackoverflow.com/questions/87542