I am using the ChannelFactory<T>
type to create channels into a WsHttpBinding
WCF web service, and the service uses a username/password combination to authenticate. While I have the authentication working using my custom validator, I am having difficulty creating channels with differing credentials.
Given the overhead of creating ChannelFactory<T>
, I'm trying to cache a single instance of it and share it for the creation of multiple channels over the lifetime of my application. Unfortunately, it seems like the credentials are directly tied to the factory and cannot be changed after a channel has been created.
In other words, if I try this:
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();
I get an exception telling me that the UserName
property is now read-only.
Is it possible to implement any sort of caching here, or am I essentially going to have to cache an instance of ChannelFactory
for every username?
As documented on MSDN this is not directly possible (Credentials
become readonly upon Open
of the ChannelFactory
)... if you really want to do this you will need to trick the ChannelFactory
like this:
// 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
Another option seems to be to Close()
the ChannelFactory
before trying to change the Credentials
.
Otherwise just stick with caching different ChannelFactories for different Credentials...
You'll need to create a new channel factory. When the factory creates the first channel, its properties become read-only (some throw the exception as you see; some others are worse in which you change but nothing happens, for example if you change some property in a binding element which you passed to the CF constructor).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With