In this article, I will give some hints on how to customize the Microsoft Enterprise Library (June 2005) for efficient usage with Visual Studio 2005.
The Enterprise Library was first released in January 2005 by the Microsoft Patterns and Practices team. The library includes a couple of application blocks (exception handling, logging, security, ...) which have formerly been published separately. An update of the Enterprise Library was released in June 2005. Both releases are designed and tested for the .NET Framework 1.1. The June 2005 release is also compatible with .NET 2.0 (after some minor modifications, see below), i.e., the library can be built with Visual Studio 2005 and it runs with the .NET Framework 2.0. (This is not true for the January 2005 release.)
The upcoming Enterprise Library 2.0 release, which will leverage the new capabilities of .NET 2.0, is announced and will soon be published. So why should you care about using the Enterprise Library June 2005 with Visual Studio 2005? The Enterprise Library 2.0 is not at all backwards compatible, there are significant changes to the internal architecture and the interfaces. Some application blocks which overlap with the new parts of the .NET 2.0 runtime library have been removed completely.
What I have in mind is a smooth migration of a (probably large) solution from .NET 1.1 / Enterprise Library June 2005 / Visual Studio 2003 to .NET 2.0 / Enterprise Library 2.0 / Visual Studio 2005. As part of such a migration, it does make sense to postpone the Enterprise Library June 2005 -> Enterprise Library 2.0 migration step, i.e., first to migrate an existing solution to Visual Studio 2005 while still using the Enterprise Library June 2005.
Building the Enterprise Library June 2005 with Visual Studio 2005
The basic steps to enable the Enterprise Library June 2005 to operate with Visual Studio 2005 are described in the Release Notes document which comes with the Enterprise Library June 2005:
- Run the Enterprise Library installation program Enterprise Library June 2005.exe. Do not select the Compile Enterprise Library option.
- Using Visual Studio 2005, open the solution file EnterpriseLibrary.sln. This solution file is located in the src folder of the Enterprise Library installation. When you open the solution, the Visual Studio Conversion Wizard will appear.
- Step through the Visual Studio Conversion Wizard and ignore any conversion errors.
- Replace all occurrences of the
#define VS2003 string with the
#define VS2005B2 string in the Enterprise Library source code.
- Save all the changes and close the solution.
- Edit the BuildLibrary.bat file. This file is located in the src folder.
- Change the
visualStudioDir variable in the script to the path of the Visual Studio 8 installation. For example, if Visual Studio 8 is installed in the default location, change the variable to C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\.
- Perform the same changes in the previous step on the InstallServices.bat file. This file is located in the src folder.
- Run the BuildLibrary.bat, CopyAssemblies.bat, and the InstallServices.bat scripts.
I did not recognize any problems when following these basic steps. There were no conversion errors from the Visual Studio Conversion Wizard, and both the Debug and the ReleaseFinal build were only producing a small number of warnings but no errors. To summarize, what you will get from these basic migration steps is a complete set of Microsoft.Practices.EnterpriseLibrary.* assemblies plus the Enterprise Library tools (Enterprise Library Configuration Tool, Security Database Console, MSMQ Distributor), all built with Visual Studio 2005 and all running with the .NET 2.0 Framework.
The Problem: the Missing Schema
The problem arises when you try to use the Visual Studio 2005 enabled version of the Enterprise Library June 2005 in an ASP.NET 2.0 web application. As soon as you start debugging your solution in Visual Studio 2005, you will get an error like this:
Error parsing application configuration file at line xxx.
is not found in Schema.
The suggested workaround (rename the current web.config and add a new one) does not solve the problem.
The problem does not arise if you Start Without Debugging (Ctrl+F5), or if you attach the debugger to a running w3wp process. Both workarounds are far away from being efficient.
I have not observed this error in a WinForms application, it is specific to web applications.
Configuring the Enterprise Library Application Blocks means adding a couple of
<configurationSection> elements to the web.config or app.config file. This can be done manually, but typically the web.config / app.config file is loaded into the EntLibConfig tool which is part of the Enterprise Library distribution. The tool provides a convenient user interface for editing the configuration sections.
Here's a typical example of the Enterprise Library configuration sections:
name="XML File Storage Provider"
name="Xml Serializer Transformer"
<keyAlgorithmStorageProvider xsi:nil="true" />
<configurationSection> associated with the XML File Storage Provider is usually referencing a satellite configuration file (dataConfiguration.config in the sample). In a large project, there might be dozens of
<configurationSection> elements with associated satellite configuration files.
While debugging an ASP.NET application in Visual Studio 2005, the parser cannot resolve the URI: xmlns="http://www.microsoft.com/practices/enterpriselibrary/08-31-2004/configuration" and triggers the error mentioned above.
The solution is quite simple:
Move all of the Enterprise Library configuration sections out of the web or app configuration files into a separate Enterprise Library main configuration file. The Enterprise Library main configuration file is referenced by an
<appSettings> key in the web / app configuration file:
This introduces two levels of redirection when looking for Enterprise Library configuration settings: follow the
entLibConfigFile key to the Enterprise Library main configuration file, then (if the requested
<configurationSection> is associated with the XML File Storage Provider) follow the
path to the satellite configuration file. In the example, the Enterprise Library main configuration file is called enterpriseLibrary.config and is expected in a subfolder named config relative to the location of the web / app configuration file.
The Enterprise Library Configuration Application Block caches configuration sections internally. So, following the twofold redirection is only necessary when reading a configuration section for the first time.
Instead of web.config / app.config, the Enterprise Library main configuration file is the one you will load into the EntLibConfig tool for editing. In fact, following this approach, web.config / app.config must no longer be loaded by EntLibConfig.
Using the EntLibConfig tool, you have the free choice to open any .NET configuration file for editing. But if you request a configuration section in code by calling
Microsoft.Practices.EnterpriseLibrary.Configuration. ConfigurationManager.GetConfiguration(), the Enterprise Library will automatically load the application configuration file (web.config / app.config). The same is true if you call any Enterprise Library method which is implicitly loading a configuration section, e.g.
So, implementing the first level of redirection requires some small modifications of the Enterprise Library sources and a rebuild of the Enterprise Library.
Open the EnterpriseLibrary.sln solution file in Visual Studio 2005 and have a look at the ConfigurationBuilder.cs class file which is part of the Configuration project. The key is the
LoadMetaConfiguration() which is called whenever a configuration section is about to be loaded, no matter if the request comes from opening a file in EntLibConfig or from calling
ConfigurationManager.GetConfiguration() in code.
Add this line of code as the first line of the
configurationFile = ConfigurationFilePicker.Lookup(configurationFile,
With this small modification, the whole method looks like this:
private void LoadMetaConfiguration(string configurationFile)
configurationFile = ConfigurationFilePicker.Lookup(configurationFile,
configFile = new ConfigurationFile(configurationFile, null);
string machineFilename = MachineConfigurationFile;
if (string.Compare(configurationFile, machineFilename,
true, CultureInfo.InvariantCulture) != 0)
ConfigurationFile machineConfigFile =
new ConfigurationFile(machineFilename, null);
configFile = new ConfigurationFile(configurationFile,
this.currentConfigFileName = configurationFile;
ConfigurationFilePicker class is available for download following the download source link at the beginning of this article. Copy the downloaded ConfigurationFilePicker.cs file to the root folder of the Configuration project (src/Configuration). Then add the file to the Configuration project. Further, add a reference to
System.Configuration to the Configuration project.
ConfigurationFilePicker class has a single
public static string Lookup(string configurationFile,
if (Assembly.GetEntryAssembly() != null)
"EntLibConfig", true, CultureInfo.InvariantCulture) == 0)
if (string.Compare(configurationFile, machineConfigurationFile,
true, CultureInfo.InvariantCulture) == 0)
throw new ConfigurationErrorsException("Loading machine.config" +
" as main configuration file is not supported here.");
NameValueCollection appSettings =
string entLibConfigFile = appSettings.Get("entLibConfigFile");
if (entLibConfigFile == null)
throw new ConfigurationErrorsException("Unable to find" +
" entLibConfigFile key in appSettings section.");
string appConfigFile =
string appConfigPath = Path.GetDirectoryName(appConfigFile);
if (!appConfigPath.EndsWith(@"\")) appConfigPath += @"\";
entLibConfigFile = entLibConfigFile.TrimStart(@"\".ToCharArray());
return appConfigPath + entLibConfigFile;
The method gets the configuration file the Configuration Application Block is about to load and redirects it to the configuration file we want to load.
First, we check whether we are called by the EntLibConfig tool. In this case, there is no redirection, i.e. the EntLibConfig tool is still allowed to open any configuration file (the user has chosen to open). Then we read the
entLibConfigFile key from the
appSettings section. Here, the name and the path of our Enterprise Library main configuration file is expected relative to the path of the application configuration file (web.config / app.config); the value of the
entLibConfigFile key is appended to this path.
You can give this approach a first try with the Security Database Console which comes with the Enterprise Library:
- Having EnterpriseLibrary.sln still open in Visual Studio 2005, set
Tools.SecurityDatabaseConsole to be the startup project.
- Add a new folder named Config to the
- Add a new application configuration file named enterpriseLibrary.config to the Config folder.
- Move both the
<configSections> and the
<enterpriselibrary.configurationSettings> elements (with all sub-elements) from app.config to enterpriseLibrary.config.
- Move all the satellite configuration files (dataConfiguration.config, securityConfiguration.config, securityCryptographyConfiguration.config) from the root folder to the Config folder.
- Add a
<appSettings> section to the app.config redirecting to the Enterprise Library main configuration file:
- Open the Properties editor of the
Tools.SecurityDatabaseConsole project. Add a new command to the Post-build event command line:
copy "$(ProjectDir)*.manifest" "$(TargetDir)" > nul
copy "$(ProjectDir)\*.config" "$(TargetDir)" > nul
xcopy "$(ProjectDir)config\*.config" "$(TargetDir)config\" /Y /R
Of course, the Security Database Console (as a WinForms application) would have run in the Visual Studio 2005 debugger without our modifications. The real interesting test is to reference the customized Enterprise Library in an ASP.NET application to see that the annoying error is gone. Also, some people might consider it to be more transparent to have the Enterprise Library configuration stuff out of the application configuration file.