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:
- Open the WCF Client project in Visual Studio
- 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
- At this point we want to revise the basic client connection code from our earlier articles into something a little more specific.
- 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.