views:

224

answers:

3

I have a solution which has multiple output projects (a website, and admin tool, and a SOAP API layer).

They each share common projects in the solution (the service layer, data layer etc). In one of these common projects, I am looking to store a config layer.

Right now, we have three seperate appsettings config files for each output project -

  • development.AppSettings.config
  • testing.AppSettings.config
  • production.AppSettings.config

So altogether, there are nine config files. Only one is used in each project, as they are referenced by utilising the configSource attribute in the web.config appsettings node.

Anyhoo, it's getting to be a pain any time we want to add/remove values from our config files, because it means that we have to change all nine files to do this. And here's what I'd like to do:

In the common project, we have three config files as above. These would be set to copy to the output directory, so that each project has a copy of them. These would be the 'base' config.

Then in each project, I would like to have three files again, but they wouldn't necessarily have to contain the same values as the base configs. If they did however, then the base config value would be overridden by the value in the output project config. A form of configuration inheritance, I suppose.

On application start, I'd like to be able to get these two config files - the base config, and the project config file. And then set the app settings accordingly.

What I'm wondering though, is what's a nice way of determining which file to use? Also, I'm wondering if this is a good way of sharing application values across a large solution, and if there's another, perhaps more efficient way of doing it?

If I'm in development mode, then I don't want production.appsettings.config, and vice versa if I'm in production mode.

Is there a simple way to get the mode (development/testing/production) that I'm in before I go off and get the configurations?

+1  A: 

You can have one set of files (3 configs) and link/share them in whatever projects you need.

http://www.devx.com/vb2themax/Tip/18855

Hope this helps.

Burt
Thank you for the answer, but I don't want to do that. The output projects need to be allowed to have their own values as well, so there needs to some form of value inheritance going on. If I change a value in project x, I don't want that value to be used in project y. However, if I change a value in the base config, then I expect projects x,y and z to have them (unless they overwrite it with their own!).
Dan Atkinson
+1  A: 

You could use the ConfigurationManager.OpenExeConfiguration static method. This will allow you to work with as many config files as you want.

You may also try creating a custom class to store all of your settings. You could then serialize your object to save it as a file. You could extend your base custom config class to fit all your other projects.

Brownman98
This may be a nice way to do the config file loading, but does it apply to configsources? It looks like it's specifically for web.configs and not files that are sections.
Dan Atkinson
A: 

After some careful thought, and a trip to the toilet at 03:30, I came across a solution which works.

Let's say that we have some appSettings in our base config file:

<add key="MyKey1" value="MyValue1" />
<add key="MyKey2" value="MyValue2" />
<!-- And so on... -->
<add key="MyKey5" value="MyValue5" />

And in my output project, I have three appSettings:

<!-- This is used to identify which config to use. -->
<add key="Config" value="Development" />

<!-- Different value to the one in the base -->
<add key="MyKey2" value="NewValue2" />

<!-- This key does not exist in the base config -->
<add key="MyKey6" value="MyValue6" />

In my Application_Start, I have a call to GetConfigs();.

And the actual GetConfigs function:

public static void GetConfigs()
{
  //Get the base config directory which is copied over to the output directory (discussed above).
  string directory = HttpContext.Current.Server.MapPath("~/bin/BaseConfig");

  //Get the config value. This is used to determine which file to open.
  string configMode = ConfigurationManager.AppSettings.Get("Config").ToLowerInvariant();

  var config = XElement.Load(string.Format(@"{0}\{1}.AppSettings.config", directory, configMode)
    .Elements("add")
    .Select(x => new { Key = x.Attribute("key").Value, Value = x.Attribute("value").Value })
    //If the current application instance does not contain this key in the config, then add it.
    //This way, we create a form of configuration inheritance.
    .Where(x => ConfigurationManager.AppSettings.Get(x.Key) == null);

  //Now loop through the base config
  foreach (var configSetting in config)
  {
    //Add a new app setting to the configuration.
    ConfigurationManager.AppSettings.Set(configSetting.Attribute("key").Value, configSetting.Attribute("value").Value);
  }
}

Now, my output project effectively has the following configuration settings:

<add key="Config" value="Development" />
<add key="MyKey1" value="MyValue1" />
<add key="MyKey2" value="NewValue2" />
<!-- And so on... -->
<add key="MyKey5" value="MyValue5" />
<add key="MyKey6" value="MyValue6" />

Simples!

Dan Atkinson