asp.net - 更改 WCF System.ServiceModel.ClientBase 的 Endpoint.Binding 不起作用

标签 asp.net wcf endpoint

我正在使用以编程方式配置的 WCF 客户端 (System.ServiceModel.ClientBase)。此 WCF 客户端使用 CustomBinding 进行配置,默认情况下具有 TextMessageEncodingBindingElement。

现在,当我尝试切换到 Mtom 编码时,我更改了 Client 的 Endpoint.Binding 属性,效果很好。 Endpoint.Binding 属性显示它已更改。

不幸的是,当我执行 WCF 服务公开的方法之一时,它仍然使用 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 不起作用吗?

最佳答案

我相信在构建ClientBase期间,原始的Binding用于创建一些辅助对象。稍后更改绑定(bind)不会更改这些辅助对象。

要在构建后进行任何调整,您可能需要自定义绑定(bind)行为,您可以根据需要调整绑定(bind)的内部结构。在构造中使用它,以便所有辅助对象都为您以后的更改做好准备。像往常一样,您想要的只是一项简单的行为更改,但您还需要编写辅助帮助器类来支持您的一项行为更改。

查看SO线程:ONVIF Authentication in .NET 4.0 with Visual Studio 2010 有关 CustomBinding 问题的讨论。

请参阅博客文章:Supporting the WS-I Basic Profile Password Digest in a WCF Client Proxy 有关可让您动态更改用户名 token 的自定义行为的示例。

也许可以做类似的事情来让您动态控制本地端点绑定(bind)。

更新:在 StackOverflow 及其链接的页面中阅读更多内容,我相信我已经找到了您正在寻找的答案。

对于PasswordDigestBehavior: 请参阅:ONVIF Authentication in .NET 4.0 with Visual Studios 2010 和:http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/

对于本地网卡绑定(bind): 请参阅:Specify the outgoing IP address to use with WCF client

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

关于asp.net - 更改 WCF System.ServiceModel.ClientBase 的 Endpoint.Binding 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10187052/

相关文章:

.net - 为 Rest Web 服务创建 WCF 代理

groovy - 如何使用属性在mockservice SOAPUI中创建资源路径

wcf - 如何以编程方式获取客户端代理正在使用的绑定(bind)?

ASP.NET MVC 4应用程序路由在azure中不起作用

asp.net - 如何正确设置 IIS6 应用程序池

.net - ChannelFactory 在端点上没有地址,为什么?

javascript - 将 Facebook Pixel 购买事件代码添加到 WooCommerce 购买完成页面

javascript - VB.NET smtp.Send 的 jQuery/JavaScript 替代方案

c# - 如何在 Asp.Net Core Web App 中向模型的一个字段添加多个值?

c# - 我应该将所有 WCF 服务代码包装在一个 try catch block 中吗?