Sharing Connection Strings & Endpoints Between WCF Services

Imagine you need to maintain several interdependent web services on a web server that call each other and some other outside web services. To add to the fun, most of them retrieve data from various SQL Server databases. In this case, the web services share several common connection string and service end points.

If the same connection string and endpoint configuration appear in several of the web services, maintaining them can be a nightmare. If a particular database connection or endpoint changes, it must be changed in each web.config file that it appears in. Add to the mix a situation where different individuals on a team are either deploying different services to the QA server or submitting deployment packages to be submitted to QA.

A solution to this problem is to share common configuration settings in a separate web.config file. Using a feature called Configuration Inheritance which has existed since ASP .NET 1.1, this can easily be done. Simply put, web.config settings in a parent web application directory are available to web applications in child directories. I wondered if one could create an ASP .NET web application directory in IIS that merely consists of a web.config file and deploy all of the web services that use these settings underneath this folder in a virtual hierarchy. All common settings would be removed from all of the web.config files for each of the web services and placed in the web.config in the parent application folder. I wanted to be sure that the web services could retrieve common connection string and service endpoint settings from this parent web.config file.

To see if this would work, I created three WCF services, ServiceOne, ServiceTwo, and ServiceThree. ServiceOne simply has a method that returns the value for a named connection string. ServiceThree has a method that returns the value of the current UTC time, and ServiceTwo simplly call the method on ServiceThree that returns the time. The connection string and endpoint information was placed in the common web.config file shown below.

Common web.config Configuration File.

[sourcecode language=”xml” title=”Config Service Web.config”]

<?xml version="1.0"?>

<configuration>
<connectionStrings>
<add name="AdventureWorks" connectionString="Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IServiceThree" >
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/WebServices/ServiceThree/ServiceThree.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IServiceThree"
contract="ServiceThree.IServiceThree" name="BasicHttpBinding_IServiceThree" />
</client>
</system.serviceModel>
</configuration>

[/sourcecode]

The web.config file was placed in http://localhost/WebServices. ServiceOne was placed in http://localhost/WebServices/ServiceOne, ServiceTwo in http://localhost/WebServices/ServiceTwo, and ServiceThree in http://localhost/WebServices/ServiceThree. Below are the web.config files for each of the three services.

ServiceOne web.config

[sourcecode language=”xml”]
<?xml version="1.0"?>
<configuration>
<connectionStrings>
</connectionStrings>
<system.web>
<compilation targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!– To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>
<serviceMetadata httpGetEnabled="true"/>
<!– To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information –>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>

</configuration>

[/sourcecode]

ServiceTwo web.config

[sourcecode language=”xml”]
<?xml version="1.0"?>
<configuration>

<system.web>
<compilation targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!– To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>
<serviceMetadata httpGetEnabled="true"/>
<!– To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information –>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>

</configuration>

[/sourcecode]

ServiceThree web.config

[sourcecode language=”xml”]
<?xml version="1.0"?>
<configuration>

<system.web>
<compilation targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!– To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>
<serviceMetadata httpGetEnabled="true"/>
<!– To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information –>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>

</configuration>

[/sourcecode]

Notice that the web.config files for each of the services do not have any connection string or service client endpoint information. Using WCF Test Client to call the service methods, I was able to verify that this concept of sharing configuration information in a parent web.config file works.

The sample solution for this post uses VS 2010 and APS .NET 4.0. Using the VS 2010 web.config transforms, the connection strings and/or service endpoint can be removed from the service web.config as it is deployed. This way, the developer can keep all of any connection string and/or service end point information in the project web.config for unit testing during development while easily being able to remove it when publishing the service. The config transform is shown for ServiceTwo below. This strips out client endpoint and related binding information from the deployed web.config for Release configuration.

ServiceTwo web.Release.config config transform.

[sourcecode language=”xml”]
<?xml version="1.0"?>

<!– For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 –>

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
</system.web>

<system.serviceModel>
<bindings xdt:Transform="Remove" />
<client xdt:Transform="Remove" />
</system.serviceModel>
</configuration>
[/sourcecode]

Sample VS 2010 solution for download:

ConfigInherit

This entry was posted in WCF and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *