更改WCF客户端主机地址-动态绑定安全性

本文关键字:动态绑定 安全性 地址 主机 WCF 客户端 更改 | 更新日期: 2023-09-27 17:59:52

我经常想在测试期间更改WCF服务客户端的主机URL。在我的配置中,我通常有一个这样的绑定:

  <basicHttpBinding>
    <binding name="ListsSoap" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="5120000" maxNameTableCharCount="16384"/>
      <security mode="Transport">
        <transport clientCredentialType="Ntlm"/>
      </security>
    </binding>

在运行时交换地址很容易:

ServiceClient svc = new ServiceClient();
svc.Endpoint.Address = new EndpointAddress("http://wherever");

问题是,如果我将地址从https更改为http,那么调用该服务会失败,因为它试图使用传输安全性,所以会说它需要https。

似乎是svc的绑定。终结点是只读的,只能在构造函数中设置。我可以使用正确的安全模式创建绑定,但随后会丢失配置文件中配置的所有其他属性值。我不想试图明确地复制它们。有没有一种方法可以使用配置文件的<binding>创建一个新的BasicHttpBinding,然后更改它的安全模式,这样我就可以使用绑定实例化svc?

更改WCF客户端主机地址-动态绑定安全性

我没有现成的服务来测试这一点,但您可以执行以下操作:

  1. 创建一个新的BasicHttpBinding,传入配置名称从您的配置文件
  2. Security.Mode设置为None
  3. 将新绑定传入服务客户端重载构造函数,该构造函数接受绑定和端点地址

类似这样的东西:

BasicHttpBinding binding = new BasicHttpBinding("ListsSoap");
binding.Security.Mode = BasicHttpSecurityMode.None;
ServiceClient svc = new ServiceClient(binding, new EndpointAddress("http://wherever"));
svc.Open();

简言之,在创建客户端之前,先完成所有绑定配置工作,因为您已经注意到,一旦创建了客户端通道,就没有什么可以更改的了。

所以这里有一个我应该如何做的例子:

public partial class ListsSoapClient
{
    protected override ListsSoap CreateChannel()
    {
#if DEBUG
        //When debugging, change the binding's security mode
        //to match the endpoint address' scheme.
        if (this.Endpoint.Address.Uri.Scheme == "https")
            ((BasicHttpBinding)this.Endpoint.Binding).Security.Mode = BasicHttpSecurityMode.Transport;
        else
            ((BasicHttpBinding)this.Endpoint.Binding).Security.Mode = BasicHttpSecurityMode.None;
#endif
        return base.CreateChannel();
    }  
}

因此,我调用该服务的代码可以保持不变:

ServiceClient svc = new ServiceClient();
svc.Call();

通过这种方式,我可以简单地更改web或app.config中的服务URL,而不必更改绑定、维护多个绑定或干扰调用源代码。这让我们少了一件在完成调试后必须记住更改的事情,如果您的团队中有不守纪律的开发人员或不了解绑定配置的开发人员,这将特别方便。CreateChannel也是在运行时设置凭据的方便场所。