14

デスクトップアプリケーションによって動的に接続された一連のWCFWebサービスがあります。

私の問題は、WCFが機能するために必要な非常に詳細な構成設定です。SSLを機能させるには、カスタム設定が必要です。MTOMまたはその他のものを機能させるには、さらに多くのことが必要です。圧縮したいですか?ああ、またか...

WCFは非常に強力です。さまざまな方法で接続できますが、すべて詳細な構成が必要なようです。ホストとクライアントが完全に一致しない場合、エラーを解読するのが難しくなります。

デスクトップアプリの構成をはるかに簡単にしたいのですが、理想的にはある種の自動検出です。デスクトップアプリのユーザーは、URLを入力するだけで、後はそれを実行できるはずです。

誰かがこれを行うための良い方法を知っていますか?

Visual Studioで構成を設定できることは知っていますが、さまざまなサーバー設定に基づいてデスクトップアプリで構成できるようにしたいと思います。

VSのツールは外部で使用できることは知っていますが、デスクトップアプリのユーザーがWCFの専門家である必要はないことを求めています。私はMSがこれを意図的に複雑にしすぎたことを知っています。

WCF設定の自動検出を可能にする方法、メカニズム、サードパーティライブラリなどはありますか?

4

3 に答える 3

9

エンドポイントに関するすべての情報は、サービスのメタデータで利用できます。サービスのメタデータを探索し、クライアントを構成するクライアントを作成できます。コード例については、Juval Lowy のこの優れたMex Explorerを参照してください。

于 2008-09-19T06:30:49.650 に答える
1

これを行う別の方法がありますが、元の質問をしたときには利用できませんでした。Microsoftは、WCFサービスのRESTをサポートするようになりました。

  • RESTを使用することの欠点は、WSDLが失われることです。
  • 利点は最小限の構成であり、WCFコントラクトインターフェイスは引き続き機能します。

次の新しい参照が必要になりますSystem.ServiceModel.Web

WebInvokeまたはのいずれかで操作をマークします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 )

これらをサイトに追加するのは簡単です-.svcファイルを追加します:

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

ファクトリラインは、エンドポイントをアクティブ化する方法をASP.netに指示します。サーバー側の構成はまったく必要ありません。

ChannelFactory次に、エンドポイントを指定する必要がないことを除いて、構築はほとんど変更されていません(または、他の回答のように1つを自動検出します)

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

クライアント構成を指定または検出していないことに注意してください。ローカル構成は必要ありません。

もう1つの大きな利点は、JSONシリアル化に簡単に切り替えることができることです。これにより、同じWCFサービスをJava、ActionScript、Javascript、Silverlight、またはJSONとRESTを簡単に処理できるその他のもので利用できます。

于 2009-12-02T16:45:10.223 に答える
1

ありがとう、それは便利なコードでした(+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;
}
于 2008-09-19T11:27:26.910 に答える