Share via


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.

Referenced Image

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.

Previous article: Common Configurations

Continue on to the next article: WCF Security in the Real World