Dot-Net
使 WCF 更易於配置
我有一組由桌面應用程序動態連接的 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; }