Click here to Skip to main content
11,639,861 members (59,404 online)
Click here to Skip to main content

Tagged as

Override Configuration Manager

, 29 Mar 2010 CPOL 19.3K 9
Rate this:
Please Sign up or sign in to vote.
Override Configuration Manager

Recently I have been working on ways to solve configuration issues in large, multi environment solutions. In the beginning, I simply wanted to store shared app settings and connection strings with a class library so I didn't have to keep copying common configuration settings from project to project within the same solution. Taking that a step further, I thought it would be great to auto detect the runtime environment and use the right app settings and connection strings from that shared configuration file. This all works great, but it has two major drawbacks: firstly, third party tools such as Elmah, and built in tools such as the Membership, Profile and Role Providers look no further than the built in ConfigurationManager object for appSettings and connection strings which forces us to subclass (Dynamically setting the Elmah connection string at runtime) or override their initialization (Setting Membership-Profile-Role provider's connection string at runtime) in order for them to work with our new settings. Not all third party tools will be as easy to fix. Secondly, all the developers working on the project must be trained to use the new techniques and always remember to use Core.Configuration.AppSettings["key"] instead of ConfigurationManager because ConfigurationManager.AppSettings["key"] may be null or hold the wrong value.

With that in mind, the next logical step was to find a way to override the built in ConfigurationManager ensuring that the Core.Configuration settings are fully integrated. In short: any call to ConfigurationManager.AppSettings or ConfigurationManager.ConnectionStrings should return the correct setting, whether that setting comes from the local web/app.config or the Core.Config. In order to do this, it is assumed that if a setting appears both in the local app/web.config and the Core.Config files, then the value in the Core.Config file will be the value returned.

Download the latest version of the Williablog.Core project: Williablog.Core.zip (110.11 kB).

Add a reference to it from your project (either to the project or the DLL in the bin folder) and the first line in void Main() of your console Application or (if a web application) Application_Start() in Global.asax should be:

Williablog.Core.Configuration.ConfigSystem.Install();

This will reinitialize the Configuration forcing it to rebuild the static cache of values but this time we are in control, and as a result we are able to effectively override the ConfigurationManager. Here is the code:

namespace Williablog.Core.Configuration
{
    using System;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.Configuration.Internal;
    using System.Reflection;

    using Extensions;

    public sealed class ConfigSystem : IInternalConfigSystem
    {
        private static IInternalConfigSystem clientConfigSystem;
        private object appsettings;
        private object connectionStrings;
        /// <span class="code-SummaryComment"><summary>
</span>

The code to actually merge our collections is implemented as Extension methods:

namespace Williablog.Core.Extensions
{
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Text;

    public static class IEnumerableExtensions
    {
        /// <span class="code-SummaryComment"><summary>
</span>

If we create a console application to test with, complete with its own app.config file that looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="WebServiceUrl" value="http://webservices.yourserver.com/YourService.asmx"/>
    <add key="SmtpServer" value="smtp.yourmailserver.com"/>
    <add key="LocalOnly" value="This is from the local app.config"/>
  </appSettings>
  <connectionStrings>
    <add name="AppData" connectionString="data source=Audi01;
	initial catalog=MyDB;User ID=User;Password=Password;"
	providerName="System.Data.SqlClient"/>
    <add name="ElmahDB" connectionString="Database=ELMAH;
	Server=Audi02;User=User;Pwd=Password;" providerName="System.Data.SqlClient"/>
  </connectionStrings>
</configuration>

And run it with the following code:

static void Main(string[] args)
{
    ConfigSystem.Install();

    Console.WriteLine(System.Configuration.ConfigurationManager.AppSettings["SmtpServer"]);
    Console.WriteLine(System.Configuration.ConfigurationManager.AppSettings["LocalOnly"]);
    Console.WriteLine
	(System.Configuration.ConfigurationManager.ConnectionStrings["AppData"]);
} 

The output is:

smtp.yourlocalmailserver.com
This is from the local app.config
data source=Ford01;initial catalog=MyDB;User ID=User;Password=Password; 

With the exception of the middle one (LocalOnly), all of these settings come from Williablog.Core.Config, not the local app.config proving that the config files were successfully merged.

The ConfigSystem class could be modified to retrieve the additional appsettings from the registry, from a database or from any other source you care to use.

I'd like to thank the contributers/authors of the following articles which I found very helpful:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Williarob
Software Developer (Senior) Salem Web Network
United States United States
Robert Williams has been programming web sites since 1996 and employed as .NET developer since its release in 2002.

You may also be interested in...

Comments and Discussions

 
GeneralJust Impressive Pin
bobsort27-Mar-13 18:01
memberbobsort27-Mar-13 18:01 
QuestionInjecting values for system.web Pin
dascalos30-Aug-11 4:21
memberdascalos30-Aug-11 4:21 
AnswerRe: Injecting values for system.web Pin
Williarob30-Aug-11 7:41
memberWilliarob30-Aug-11 7:41 
GeneralRe: Injecting values for system.web Pin
dascalos31-Aug-11 3:08
memberdascalos31-Aug-11 3:08 
Thank you. That does exactly what I needed to do. I was headed down the wrong path.
QuestionHow can i get different group values? [modified] Pin
ashutosh30076-Aug-10 0:25
memberashutosh30076-Aug-10 0:25 
AnswerRe: How can i get different group values? Pin
Williarob6-Aug-10 2:58
memberWilliarob6-Aug-10 2:58 
QuestionWCF Config ? Pin
lbogni17-May-10 12:16
memberlbogni17-May-10 12:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150731.1 | Last Updated 29 Mar 2010
Article Copyright 2010 by Williarob
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid