2

プログラムで構成された WCF クライアント (System.ServiceModel.ClientBase) を使用しています。この WCF クライアントは、既定で TextMessageEncodingBindingElement を持つ CustomBinding を使用して構成されます。

Mtom エンコーディングに切り替えようとすると、Client の Endpoint.Binding プロパティを変更すると正常に動作します。Endpoint.Binding プロパティは、変更されたことを示しています。

残念ながら、WCF サービスが公開しているメソッドの 1 つを実行すると、依然として TextMessageEncoding が使用され、その理由がわかりません。

ただし、新しい ClientBase を構築し、コンストラクターで新しい EndPointBinding を渡すことで、機能しています。

socialProxy = new SocialProxyClient(SocialProxyClientSettings.SocialProxyMTomEndPointBinding, new EndpointAddress(SocialProxyClientSettings.SocialProxyEndPointAddress));

しかし、これを試してみるとうまくいきません:

socialProxy.Endpoint.Binding = SocialProxyClientSettings.SocialProxyMTomEndPointBinding;

これらは、EndPointBindings の私の定義です。

public static TextMessageEncodingBindingElement TextMessageEncodingBindingElement
{
    get
    {
        if (_textMessageEncodingBindingElement == null)
        {
            _textMessageEncodingBindingElement = new TextMessageEncodingBindingElement() { MessageVersion = MessageVersion.Soap11 };
            _textMessageEncodingBindingElement.ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
            {
                MaxDepth = 32,
                MaxStringContentLength = 5242880,
                MaxArrayLength = 204800000,
                MaxBytesPerRead = 5242880,
                MaxNameTableCharCount = 5242880
            };
        }
        return _textMessageEncodingBindingElement;
    }
}

public static MtomMessageEncodingBindingElement MtomMessageEncodingBindingElement
{
    get
    {
        if (_mtomMessageEncodingBindingElement == null)
        {
            _mtomMessageEncodingBindingElement = new MtomMessageEncodingBindingElement();
            _mtomMessageEncodingBindingElement.MaxReadPoolSize = TextMessageEncodingBindingElement.MaxReadPoolSize;
            _mtomMessageEncodingBindingElement.MaxWritePoolSize = TextMessageEncodingBindingElement.MaxWritePoolSize;
            _mtomMessageEncodingBindingElement.MessageVersion = TextMessageEncodingBindingElement.MessageVersion;
            _mtomMessageEncodingBindingElement.ReaderQuotas.MaxDepth = TextMessageEncodingBindingElement.ReaderQuotas.MaxDepth;
            _mtomMessageEncodingBindingElement.ReaderQuotas.MaxStringContentLength = TextMessageEncodingBindingElement.ReaderQuotas.MaxStringContentLength;
            _mtomMessageEncodingBindingElement.ReaderQuotas.MaxArrayLength = TextMessageEncodingBindingElement.ReaderQuotas.MaxArrayLength;
            _mtomMessageEncodingBindingElement.ReaderQuotas.MaxBytesPerRead = TextMessageEncodingBindingElement.ReaderQuotas.MaxBytesPerRead;
            _mtomMessageEncodingBindingElement.ReaderQuotas.MaxNameTableCharCount = TextMessageEncodingBindingElement.ReaderQuotas.MaxNameTableCharCount;
        }
        return _mtomMessageEncodingBindingElement;
    }
}

Endpoint.Binding をプログラムで変更してもうまくいかない理由を誰かが説明できますか?

4

1 に答える 1

3

ClientBase の構築中に、元の Binding を使用していくつかのヘルパー オブジェクトが作成されると思います。バインディングを後で変更しても、これらのヘルパー オブジェクトは変更されません。

構築後に調整を行うには、必要に応じて Binding の内部を微調整できるカスタム Binding Behavior が必要になる可能性があります。それを構築に使用して、すべてのヘルパー オブジェクトが後で変更できるように準備します。いつものように、必要なのは 1 つの単純な動作の変更だけですが、1 つの動作の変更をサポートする補助的なヘルパー クラスも作成する必要があります。

SO スレッドを参照してください: CustomBinding の問題については、Visual Studio 2010 を使用した .NET 4.0 での ONVIF 認証。

ユーザー名トークンをその場で変更できるカスタム動作の例については、ブログ投稿: WCF クライアント プロキシでの WS-I 基本プロファイル パスワード ダイジェストのサポートを参照してください。

おそらく、ローカル エンドポイント バインディングをその場で制御できるようにするために、同様のことを行うことができます。

更新: ここで StackOverflow とそれがリンクしているページの詳細を読んでください。あなたが探している答えが見つかったと思います。

PasswordDigestBehavior については、「 Visual Studio 2010 を使用した .NET 4.0 での ONVIF 認証」 および「http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy 」を参照してください。 /

ローカル NIC バインディングの場合: 参照: WCF クライアントで使用する発信 IP アドレスを指定する

// ASSUMPTIONS:
//  1: DeviceClient is generated by svcutil from your WSDL.
//  1.1: DeviceClient is derived from
//           System.ServiceModel.ClientBase<Your.Wsdl.Device>
//  2: serviceAddress is the Uri provided for your service.
//
private static DeviceClient CreateDeviceClient(IPAddress nicAddress,
                                               Uri serviceAddress,
                                               String username,
                                               String password)
{
    if (null == serviceAddress)
        throw new ArgumentNullException("serviceAddress");

    //////////////////////////////////////////////////////////////////////////////
    // I didn't know how to put a variable set of credentials into a static
    //  app.config file.
    // But I found this article that talks about how to set up the right kind
    //  of binding on the fly.
    // I also found the implementation of PasswordDigestBehavior to get it all to work.
    //
    // from: https://stackoverflow.com/questions/5638247/onvif-authentication-in-net-4-0-with-visual-studios-2010
    // see: http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/
    //
    EndpointAddress serviceEndpointAddress = new EndpointAddress(serviceAddress);
    HttpTransportBindingElement httpBinding = new HttpTransportBindingElement();
    if (!String.IsNullOrEmpty(username))
    {
        httpBinding.AuthenticationScheme = AuthenticationSchemes.Digest;
    }
    else
    {
        httpBinding.AuthenticationScheme = AuthenticationSchemes.Anonymous;
    }
    var messageElement = new TextMessageEncodingBindingElement();
    messageElement.MessageVersion =
       MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None);

    CustomBinding bind = new CustomBinding(messageElement, httpBinding);

    ////////////////////////////////////////////////////////////////////////////////
    // from: https://stackoverflow.com/questions/3249846/specify-the-outgoing-ip-address-to-use-with-wcf-client
    //  Adjust the serviceEndpointAddress to bind to the local NIC, if at all possible.
    //
    ServicePoint sPoint = ServicePointManager.FindServicePoint(serviceAddress);
    sPoint.BindIPEndPointDelegate = delegate(
            System.Net.ServicePoint servicePoint,
            System.Net.IPEndPoint remoteEndPoint,
            int retryCount)
    {
        // if we know our NIC local address, use it
        //
        if ((null != nicAddress)
            && (nicAddress.AddressFamily == remoteEndPoint.AddressFamily))
        {
            return new System.Net.IPEndPoint(nicAddress, 0);
        }
        else if (System.Net.Sockets.AddressFamily.InterNetworkV6 == remoteEndPoint.AddressFamily)
        {
            return new System.Net.IPEndPoint(System.Net.IPAddress.IPv6Any, 0);
        }
        else // if (System.Net.Sockets.AddressFamily.InterNetwork == remoteEndPoint.AddressFamily)
        {
            return new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0);
        }
    };
    /////////////////////////////////////////////////////////////////////////////

    DeviceClient client = new DeviceClient(bind, serviceEndpointAddress);

    // Add our custom behavior
    //  - this requires the Microsoft WSE 3.0 SDK file: Microsoft.Web.Services3.dll
    //
    PasswordDigestBehavior behavior = new PasswordDigestBehavior(username, password);
    client.Endpoint.Behaviors.Add(behavior);

    return client;
}
于 2012-10-02T18:08:20.563 に答える