views:

404

answers:

8

Dear ladies and sirs.

I have a client-server application, where there two options for the server - standalone executable or in another AppDomain in the client, which is very convenient for the debugging purposes. The choice of the server is transparent to the client, the only file that needs to be changed is the client app.config.

In order to switch from the standalone server to the local one, some sections need to be un-commented (like nhibernate configuration, which is only relevant to the server) along with individual settings (like authentication implementation, which is again only relevant to the server).

As of now, switching between the two modes is tedious and error prone, because one has to (un)comment several sections and individual settings.

Is there a way to specify conditional settings/sections in app.config? Or maybe there is a way to include another config file in the app.config? This way we could put all the local server specific settings in another file and only (un)comment its inclusion.

I would like to stress the fact, that I wish to have conditional sections, in addition to application settings.

Final note. The described scenario is obviously not for production. It is used exclusively for running unit tests. We use mstest for our unit tests.

Thanks.

+1  A: 

One approach is to use build events. Create two application settings files each named according to the type of deployment. Create a new build configuration for each type of deployment.

Have a pre-build event that determines the type of build configuration that is being executed and then create the "app.config" file by copying the specialized config file and naming it "app.config".

j0rd4n
+3  A: 

In ASP.NET it is possible to have some settings in an external file (but I'm not sure if this is also available in windows apps):

Update: this also works for console/winforms applications.

web.config/app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <!-- comment one of the following two lines -->

  <!--appSettings-->
  <appSettings file="YourSettings.config">

    <add key="KeyToOverride" value="Original" />
    <add key="KeyToNotOverride" value="Standard" />

  </appSettings>
</configuration>

YourSettings.config:

<appSettings>
  <add key="KeyToOverride" value="Overridden" />
  <add key="KeyToBeAdded" value="EntirelyNew" />
</appSettings>
M4N
Yes, but what about sections? NHibernate, log4net, other libraries define their own configuration sections. Can they be moved to another configuration file? According to MSDN - not.
mark
A: 

nAnt may be another solution.

JB King
nAnt, if I am not mistaken, is a build tool. Like msbuild, maven or make. How using it can help me with managing the application configuration settings?
mark
It is a script tool that can do builds, run tests and handle setting application configuration settings as where I work we use it to generate some app.config and web.config files in our projects. I am somewhat presuming that such a tool could be used to automate the changes of the configuration files through a command line interface that is an acceptable approach to solve the problem.
JB King
We are using msbuild. We use it to build, run static code analysis (using fxcop) and invoke our unit tests as well as do a few other things. As far as I know it is as capable as Nant. I guess it can be used to create app.config file from some kind of a template based on some command line parameter. This is the last resort, if nothing else works.
mark
+1  A: 

Add a new setting - AppType = Server/Standalone - duplicate each setting within App.Config that changes based on Server/Standalone so that there is just 1 app.config regardless of Server/Standalone. Move the conditional choices into your App.

if(AppType == ApplicationType.Server)
{
   Setup(NHibernate);
   Setup(Authentication Implementation);
}
else
{
   Setup(Standalone app stuff);
}
s_hewitt
Exactly. Create separate sections in the App.Config file and control which one is loaded by a command line switch to the application.
Jim Mischel
Does not look like we can use this approach. Some settings are intended for 3rd party libraries (like CSLA, log4net, etc ...), which read them at their own convenience. It is unclear how to extend the NHibernate example to a general case.
mark
+1  A: 

The app.config or web.config file can reference an external config file.

<configuration>
  <appSettings file="external.config">
  </appSettings>
</configuration>

MSDN appSettings reference

Mircea Grelus
Yes, but what about sections? NHibernate, log4net, other libraries define their own configuration sections. Can they be moved to another configuration file? According to MSDN - not.
mark
+1  A: 

System.Configuration supports include files with configsource attribute. See here http://msdn.microsoft.com/en-us/library/system.configuration.sectioninformation.configsource.aspx or here http://rizwanshah.blogspot.com/2007/10/use-configsource-attribute-to-manage.html

You can use it like this:

<SomeSection configSource="myOtherFile.config" />

We've used to add differing sections to declarative wcf configuration etc/

Preet Sangha
If there are two different sections, then there should be two different configSource files? Or one file can contain different sections and be the configSource for several distinct sections?
mark
not sure - we done it by having different sections in different files only. Not checked it the other way
Preet Sangha
Unfortunately you do have to use one file per section type. See my answer for an alternative that should be almost as easy for you to work with.
MattH
Thank you for that info Matt.
Preet Sangha
A: 

Simple answer: Just use a command line argument. I am currently working on a project which needs to switch between 'local' (for testing / debugging purposes) and 'server' (when I deploy it to a production machine). I just have visual studio pass 'local' as a command line argument when I'm in debug mode, and use the presence of that argument to configure the software at runtime to do what I need it to do.

The absence of any argument causes the software to behave as if it's in production. When the software is ready for release, I'll just remove the argument logic entirely.

TomFromThePool
A: 

For your normal appSettings the norm would be to use this:

<appSettings file="appSettings.config" />

For other sections you can use

<mySection configSource="mySection.config" />

You have to have a file per section, and the configSource will only work with relative paths.

For your particular case, I would recommend a folder for each setup/configuration.

<mySection1 configSource="setup1\mySection1.config" />
<mySection2 configSource="setup1\mySection2.config" />

Then you can manually do a text 'find and replace' on the folder name to switch between setups, or run a batch file or build step that switches the folder on the file system (i.e. copy the setup1 folder to a currentSetup folder)

Note that you can't use a configSource on system.serviceModel, but you can for its subsections

MattH
What happens if configSource refers a non existing file? Is the section silently ignored or application simply fails to configure itself?
mark
You should get an application configuration error, even if the configuration element is optional
MattH