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

时间:2015-06-25 21:46:14

标签: c# wcf configuration

我经常想在测试期间更改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.Endpoint的绑定是只读的,只能在构造函数中设置。我可以使用正确的安全模式创建绑定,但后来我丢失了配置文件中配置的所有其他属性值。我不想尝试明确地复制它们。有没有办法使用配置文件<binding>创建一个新的BasicHttpBinding,然后更改它的安全模式,以便我可以使用绑定实例化svc?

2 个答案:

答案 0 :(得分:1)

我没有提供便于测试的服务,但您可以执行以下操作:

  1. 创建新的BasicHttpBinding,传入配置名称 来自您的配置文件。
  2. Security.Mode设置为None
  3. 将新绑定传递给服务客户端重载构造函数,该构造函数接受绑定和端点地址。
  4. 这样的事情:

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

    简而言之,在创建客户端之前,请执行所有绑定配置工作,因为一旦创建了客户端通道,您已经注意到了,您可以更改它们。

答案 1 :(得分:0)

所以这是我将如何做的一个例子:

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也是在运行时设置凭据的便利位置。