Simplifying Enterprise Library Configuration
Applies to: Windows Communication Foundation
Published: June 2011
Author: Alex Culp
Summary: This article discusses some different strategies for the configuration of enterprise-scale WCF services.
This topic contains the following sections.
- Enterprise Library Fluent Interface
- Centralizing Enterprise Library Configuration with Slight Differences Between Services
- Additional Resources
Although Enterprise Library is not designed specifically for WCF services, a great many WCF services rely on Enterprise Library for logging, exception management, data access, and dependency injection. This section describes how to simplify your Enterprise Library configuration information. One of the biggest complaints from customers about Enterprise Library is the sheer amount of configuration that it requires. It can be difficult to manage the configuration files, particularly if you use multiple application blocks.
Enterprise Library Fluent Interface
If you are willing to lose some flexibility, you can easily configure Enterprise Library programmatically, instead of with configuration files. Enterprise Library 5.0 includes a fluent interface that allows you to configure the application blocks. The following code is an example of how you can configure the Exception Handling Application Block.
Visual C# Example Enterprise Library Configuration with Fluent Interface
var builder = new ConfigurationSourceBuilder();
builder.ConfigureExceptionHandling()
.GivenPolicyWithName(policy.ToString())
.ForExceptionType<Exception>()
.LogToCategory("General")
.UsingEventId(eventId).UsingTitle(ex.Message);
var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
Visual Basic Example Enterprise Library Configuration with Fluent Interface
Dim builder = New ConfigurationSourceBuilder()
builder.ConfigureExceptionHandling().GivenPolicyWithName(policy.ToString()).ForExceptionType(Of Exception)().LogToCategory("General").UsingEventId(eventId).UsingTitle(ex.Message)
Dim configSource = New DictionaryConfigurationSource()
builder.UpdateConfigurationWithReplace(configSource)
EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource)
Centralizing Enterprise Library Configuration with Slight Differences Between Services
The strategy described in the previous section is also useful if the services' configuration files have only a few differences. You do not want to duplicate entire configuration files when only one or two attributes or elements are different. A good example is the configuration file for the Exception Handling Application Block. The only difference between services may be the title or the event ID that is used when an error occurs. The following XML code is an example of a centralized configuration.
Example Centralized Exception Management Configuration
<exceptionHandling>
<exceptionPolicies>
<add name="GeneralPolicy">
<exceptionTypes>
<add type="System.Data.SqlClient.SqlException, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
postHandlingAction="None" name="SqlException">
<exceptionHandlers>
<add logCategory="Exceptions" eventId="[Event Id]" severity="Error"
title="[Exception Title]" formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.XmlExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
priority="0" useDefaultLogger="false" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="LogHandler:GeneralPolicy.System.Data.SqlClient.SqlException" />
</exceptionHandlers>
</add>
<add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
postHandlingAction="None" name="Exception">
<exceptionHandlers>
<add logCategory="Exceptions" eventId="[Event Id]" severity="Error"
title="[Exception Title]" formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.XmlExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
priority="0" useDefaultLogger="false" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="LogHandler:GeneralPolicy.System.Exception" />
</exceptionHandlers>
</add>
</exceptionTypes>
</add>
<add name="WarningPolicy">
<exceptionTypes>
<add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
postHandlingAction="None" name="GeneralWarningPolicySystemException">
<exceptionHandlers>
<add logCategory="Warnings" eventId="[Event Id]" severity="Warning"
title="Exception Title" formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.XmlExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
priority="0" useDefaultLogger="false" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="LogHandler:WarningPolicy.System.Exception" />
</exceptionHandlers>
</add>
</exceptionTypes>
</add>
</exceptionPolicies>
</exceptionHandling>
Note
For each of the exception types, there is a unique name that follows a consistent naming convention. This practice simplifies the XPath that is necessary to modify specific elements in the service-specific configuration.
<exceptionHandling xmlns:xdt="https://schemas.microsoft.com/XML-Document-Transform" >
<exceptionPolicies>
<add>
<exceptionTypes>
<add>
<exceptionHandlers>
<add title="An unexpected error occurred in the Service1 service" eventId="100" xdt:Transform="SetAttributes(title,eventId)" xdt:Locator="Condition(@name='LogHandler:GeneralPolicy.System.Exception')" />
<add title="An unexpected SQL error occurred in the Service1 service" eventId="101" xdt:Transform="SetAttributes(title,eventId)" xdt:Locator="Condition(@name='LogHandler:GeneralPolicy.System.Data.SqlClient.SqlException')" />
<add title="An unexpected error occurred in the Service1 service" eventId="102" xdt:Transform="SetAttributes(title,eventId)" xdt:Locator="Condition(@name='LogHandler:WarningPolicy.System.Exception')" />
</exceptionHandlers>
</add>
</exceptionTypes>
</add>
</exceptionPolicies>
</exceptionHandling>
Note
The specific transformation xdt:Transform="SetAttributes(title,eventId) only transforms the values of the title, and eventID attributes.
In the .csproj file, instead of using an environment variable, you can create a transform task for each service in the solution. The following XML code is an example of how to do this.
<!--Transform and copy exceptions configuration-->
<TransformXml Source="$(ProjectDir)Exceptions.config" Transform="$(ProjectDir)Exceptions.Service1.config" Destination="$(SolutionDir)Service1\Exceptions.config" />
<TransformXml Source="$(ProjectDir)Exceptions.config" Transform="$(ProjectDir)Exceptions.Service2.config" Destination="$(SolutionDir)Service2\Exceptions.config" />
<TransformXml Source="$(ProjectDir)Exceptions.config" Transform="$(ProjectDir)Exceptions.Service3.config" Destination="$(SolutionDir)Service3\Exceptions.config" />
The result is that you now have a unique Exceptions.config file at the root of each service project in your solution. You can now modify the behavior of any exception that affects all services without having to duplicate the same change across every service.
Additional Resources
For more information, see the following resources.
Enterprise Library 5.0 Download: https://www.microsoft.com/downloads/en/details.aspx?FamilyId=bcb166f7-dd16-448b-a152-9845760d9b4c
Enterprise Library Fluent Interface: https://msdn.microsoft.com/en-us/library/microsoft.practices.enterpriselibrary.common.configuration.fluent(v=pandp.50).aspx
SectionInformation.ConfigSource Property: https://msdn.microsoft.com/en-us/library/system.configuration.sectioninformation.configsource.aspx
Web Deployment: Web.Config Transformation: https://blogs.msdn.com/b/webdevtools/archive/2009/05/04/web-deployment-web-config-transformation.aspx
Web.config Transformation Syntax for Web Application Project Deployment: https://msdn.microsoft.com/en-us/library/dd465326.aspx
Previous article: Common Configurations
Continue on to the next article: WCF Security in the Real World