Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ChannelFactory<T> To Create Channels with Different Credentials

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?

like image 961
Adam Robinson Avatar asked Dec 22 '22 07:12

Adam Robinson


2 Answers

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...

like image 58
Yahia Avatar answered Feb 15 '23 23:02

Yahia


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).

like image 37
carlosfigueira Avatar answered Feb 16 '23 01:02

carlosfigueira