我使用ChannelFactory<T>
类型在WsHttpBinding
WCF Web服务中创建频道,该服务使用用户名/密码组合进行身份验证。虽然我使用自定义验证器进行身份验证,但我在创建具有不同凭据的频道时遇到了困难。
考虑到创建ChannelFactory<T>
的开销,我正在尝试缓存它的单个实例并共享它,以便在我的应用程序生命周期内创建多个通道。不幸的是,似乎凭证直接与工厂绑定,并且在创建通道后无法更改。
换句话说,如果我试试这个:
factory.Credentials.UserName.UserName = "Bob";
factory.Credentials.UserName.Password = "password";
var channel1 = factory.CreateChannel();
factory.Credentials.UserName.UserName = "Alice"; // exception here
factory.Credentials.UserName.Password = "password";
var channel1 = factory.CreateChannel();
我得到一个异常,告诉我UserName
属性现在是只读的。
是否可以在此处实现任何类型的缓存,或者我实际上是否必须为每个用户名缓存ChannelFactory
的实例?
答案 0 :(得分:7)
As documented on MSDN这不是直接可能的(Credentials
仅在Open
ChannelFactory
时成为只读...如果你真的想要这样做,你需要欺骗ChannelFactory
就像这样:
// step one - find and remove default endpoint behavior
var defaultCredentials = factory.Endpoint.Behaviors.Find<ClientCredentials>();
factory.Endpoint.Behaviors.Remove(defaultCredentials);
// step two - instantiate your credentials
ClientCredentials loginCredentials = new ClientCredentials();
loginCredentials.UserName.UserName = "Username";
loginCredentials.UserName.Password = "Password123";
// step three - set that as new endpoint behavior on factory
factory.Endpoint.Behaviors.Add(loginCredentials); //add required ones
在尝试更改Close()
之前,另一个选项似乎是ChannelFactory
Credentials
。
否则只需坚持为不同的凭据缓存不同的ChannelFactories ......
答案 1 :(得分:2)
您需要创建一个新的渠道工厂。当工厂创建第一个通道时,它的属性变为只读(有些会抛出异常,如你所见;有些更糟糕的是你改变但没有任何反应,例如,如果你更改了传递给你的绑定元素中的某个属性CF构造函数)。