Creating a WCF Client Part 4: Programmatically configuring WCF Clients


While using the app.config file is a quick & convenient (Article 2, Article 3) way to get your WCF clients up and running, there are times when you may not want to distribute a .exe.config file alongside your EXE. This article describes how to configure a WCF client on-the-fly in your C# Code.

 

Here are the steps I took to convert one of my WCF Clients to use an on-demand configuration approach:

 

  1. Open the WCF Client project in Visual Studio
  2. Cut out the parts of the app.config file pertaining to web services (see Article #2 for an example) and paste them into a notepad document for reference
  3. At this point we want to revise the basic client connection code from our earlier articles into something a little more specific.
  4. As we have removed the client configuration settings from the app.config file, we need to:
  • Define a Binding
    • Needs a unique Name
    • A number of properties must be set
  • Define an Endpoint Address
    • Should have a unique Name
    • Needs a URI of the web service you want to hit
  • Instantiate the WCF Client object by constructor
    • Explicit Binding
    • Explicit Endpoint Address

Note: You can find all of the necessary settings for the Binding and Endpoint Address by looking through the sections of the app.config that you copied out in Step 2 above.

Our code goes from looking something like this:

// Instantiates a client object
SomeServiceClient client = new SomeServiceClient();

// Opens the client object
client.Open();

//
// Between the open & close, you would use any methods made available in the class.
// For example, if the client provided a method named ReturnDataTable which
// Returns a data table, you could do something like this:

DataTable results = client.ReturnDataTable();

// Closes the client object
client.Close();

 

To something that is a little more complex. I've added comments around the major sections for clarity:

 

// ----- Programmatic definition of the SomeService Binding -----

System.ServiceModel.BasicHttpBinding SomeServiceBinding = new System.ServiceModel.BasicHttpBinding();

SomeServiceBinding.Name = "SomeServiceServiceBinding";

SomeServiceBinding.CloseTimeout = new TimeSpan(0, 1, 0);
SomeServiceBinding.OpenTimeout = new TimeSpan(0, 1, 0);
SomeServiceBinding.ReceiveTimeout = new TimeSpan(0, 1, 0);
SomeServiceBinding.SendTimeout = new TimeSpan(0, 1, 0);

SomeServiceBinding.AllowCookies = false;
SomeServiceBinding.BypassProxyOnLocal = false;
SomeServiceBinding.HostNameComparisonMode = System.ServiceModel.HostNameComparisonMode.StrongWildcard;
SomeServiceBinding.MaxBufferSize = 65536;
SomeServiceBinding.MaxBufferPoolSize = 524288;
SomeServiceBinding.MaxReceivedMessageSize = 65536;
SomeServiceBinding.MessageEncoding= System.ServiceModel.WSMessageEncoding.Text;
SomeServiceBinding.TextEncoding = System.Text.Encoding.UTF8;
SomeServiceBinding.TransferMode = System.ServiceModel.TransferMode.Buffered;
SomeServiceBinding.UseDefaultWebProxy = true;

SomeServiceBinding.ReaderQuotas.MaxDepth = 32;
SomeServiceBinding.ReaderQuotas.MaxStringContentLength = 8192;
SomeServiceBinding.ReaderQuotas.MaxArrayLength = 16384;
SomeServiceBinding.ReaderQuotas.MaxBytesPerRead = 4096;
SomeServiceBinding.ReaderQuotas.MaxNameTableCharCount = 16384;

SomeServiceBinding.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport;
SomeServiceBinding.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.None;
SomeServiceBinding.Security.Transport.ProxyCredentialType = System.ServiceModel.HttpProxyCredentialType.None;
SomeServiceBinding.Security.Message.ClientCredentialType = System.ServiceModel.BasicHttpMessageCredentialType.UserName;
SomeServiceBinding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Default;
// ----------- End Programmatic definition of the SomeServiceServiceBinding --------------

// ---------- Configure a Remote Address Manually ----------------
System.ServiceModel.EndpointAddress SomeServiceServerAddress = new
System.ServiceModel.EndpointAddress("https://someservices.mydomain.com:809/Services/SomeOtherServices.svc");
// -----------End configure remote address manually --------------

// ----------- Instantiate & Open the Client object ----------
SomeServiceClient client = new SomeServiceClient(SomeServiceBinding, SomeServiceServerAddress);

client.Open();

//
// Between the open & close, you would use any methods made available in the class.
// For example, if the client provided a method named ReturnDataTable which
// Returns a data table, you could do something like this:

DataTable results = client.ReturnDataTable();

// Close the client object
client.Close();

 

~Troubleshooting~

Configuration system failed to initialize

See the end of this message for details on invoking just-in-time (JIT) debugging instead of this dialog box.
 
** Exception Text **
System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize ---> System.Configuration.ConfigurationErrorsException: Unrecognized configuration section userSettings. (C:\Users\Administrator\AppData\Local\SomeCompany\SomeWCFClient.exe_Url_fwt2rqjtqtwa4i3g42pr3zwuekhsbjwz\1.7.6.0\user.config line 3)
   at System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors(Boolean ignoreLocal)
   at System.Configuration.BaseConfigurationRecord.ThrowIfInitErrors()
   at System.Configuration.ClientConfigurationSystem.OnConfigRemoved(Object sender, InternalConfigEventArgs e)
   --- End of inner exception stack trace ---

 

You may need to remove the user.config file or the automatically generated "program name" folder for your executable from C:\Users\appdata\local\CompanyName (for Windows Server 2008 R2). It looks like settings from app.config can become cached here, and when the app starts again it receives a configuration it doesn't quite understand.