Loading WCF Client Configuration from Different Files with ConfigurationChannelFactory

Loading WCF Client Configuration from Different Files with ConfigurationChannelFactory

  • Comments 5

One pain point with configuration that WCF developers have run into in previous versions of the framework is the limitation that WCF clients can only use the hosting executable’s configuration file. This can be problematic for clients that need to call multiple services because the configuration for all of these services would have to be mashed together in one big configuration file. This can also be a problem for client libraries: since libraries don’t have configuration files, every executable that uses the library needs to provide it with the right configuration in its own configuration file.

Fortunately, this restriction has been lifted in WCF 4.0 with the introduction of ConfigurationChannelFactory. This new class allows you to create clients that can take in any Configuration object to configure your client. This means that you’re no longer limited to using the App.config for your executable. To demonstrate this new class, let’s say you have a client that needs to call out to a web service that returns stock information and another web service that returns weather information.

 

In WCF 4.0, you can do this:

 

Configuration stockConfiguration = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap { ExeConfigFilename = @"C:\Temp\StockClient.config"}, ConfigurationUserLevel.None);

ConfigurationChannelFactory<StockQuoteSoap> stockChannelFactory = new ConfigurationChannelFactory<StockQuoteSoap>("StockQuoteSoap", stockConfiguration, null);

StockQuoteSoap stockClient = stockChannelFactory.CreateChannel();

GetQuoteResponse stockResponse = stockClient.GetQuote(new GetQuoteRequest { Body = new GetQuoteRequestBody { symbol = "MSFT" } });

Console.WriteLine(stockResponse.Body.GetQuoteResult);

stockChannelFactory.Close();

 

Configuration weatherConfiguration = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap { ExeConfigFilename = @"C:\Temp\WeatherClient.config" }, ConfigurationUserLevel.None);

ConfigurationChannelFactory<GlobalWeatherSoap> weatherChannelFactory = new ConfigurationChannelFactory<GlobalWeatherSoap>("GlobalWeatherSoap", weatherConfiguration, null);

GlobalWeatherSoap weatherClient = weatherChannelFactory.CreateChannel();

GetWeatherResponse weatherResponse = weatherClient.GetWeather(new GetWeatherRequest { Body = new GetWeatherRequestBody { CityName = "Paris", CountryName = "France" } });

Console.WriteLine(weatherResponse.Body.GetWeatherResult);

weatherChannelFactory.Close();

 

In this example, two separate client configuration files are located at C:\Temp\StockClient.config and C:\Temp\WeatherClient.config and we’re able to use both in the very same method! For each service, we first load up a configuration object, then pass that configuration object to the constructor for ConfigurationChannelFactory, and finally call the service and print out the results. It's that easy.

Leave a Comment
  • Please add 6 and 8 and type the answer here:
  • Post
  • Good stuff.  Could you also indicate how this is to be used in conjunction with ClientBase<TChannel>, which svcutil-generated code uses?  Thanks.

  • If i give pass ExeConfigFilename as string,please find the code below

    Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap() { ExeConfigFilename = path }, ConfigurationUserLevel.None);

    It throws error "An unexpected error occurred in 'ClientConfigurationHost::Init'."

    It work fine for the below code

    Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap { ExeConfigFilename = @"D:\test.config" }, ConfigurationUserLevel.None);

  • Do you also know of a way to have the <system.serviceModel><diagnostics><endToEndTracing .../>/>/> taken from somewhere other than app/web.config?  Our current project has an Excel plugin which calls out to our WCF service and I want to flow ActivityID across that call via propagateActivity="true", but I can't go creating/messing with Excel.exe.config.  So instead I want to enable this from a central config (like we have done using ConfigurationChannelFactory for the client/service config), or programmatically. Any suggesions?

  • This is very useful. I am writing in C#. I used your above code but am still having a problem when I call the newConfigurationChannelFactory:

    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();

               fileMap.ExeConfigFilename = "app.config";

               Configuration newConfiguration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

               ConfigurationChannelFactory<IAlgorithm1> factory = new ConfigurationChannelFactory<IAlgorithm1>("WSHttpBinding_IAlgorithm1",

                                       newConfiguration, new EndpointAddress("http://localhost:8000/TechnicalAnalysis/Algorithm1"));

               IAlgorithm1 algo = factory.CreateChannel();

    I get the error message when it gets to the factory code:

       ConfigurationChannelFactory<IAlgorithm1> factory = new ConfigurationChannelFactory<IAlgorithm1>("WSHttpBinding_IAlgorithm1",

                                       newConfiguration, new EndpointAddress("http://localhost:8000/TechnicalAnalysis/Algorithm1"));

    I get the following error:

    Could not find endpoint element with name 'WSHttpBinding_IAlgorithm1' and contract 'IAlgorithm1' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this name could be found in the client element.

    Am wondering whether the client generated code (which I originally generated with a config file using svcutil) needs to be changed.

    Any ideas?

    Thanks!

  • stackoverflow.com/.../convert-web-service-configuration-to-code

Page 1 of 1 (5 items)