views:

985

answers:

5

Is it possible to modify the connectionstrings defined in the app.config/web.config at runtime? I want to use different configfiles depending on the machine the app/site is run on (only for debugging purposes, of course. We'll use the regular config files when deployed).

I can write AppSettings, but not ConnectionStrings (AFAIK). Or can I?

A: 

You can't really edit the config file of the running process.

One option (with pros and cons) is to use config data in the machine.config or the master web.config (for "site", you use the "location" nodes) - not an option to rush into, though.

A better way to handle this is to swap the config file as part of your build/deploy process, ideally automated. That way, everything is self-contained, and you can "robocopy" to a vanilla server and have it work.


Re your "per developer" point; I found that the easiest way to do this was to standardise the config, and tweak the machines. For example, we run a local web-server on a VM; rather than code against each machine, we standardise on "localserver" (to mirror "localhost"), and add a local DNS record to each machine that the developer can control. Note that this requires fixed IP addresses (or maybe a DHCP reservation) to prevent it changing over time!

Ditto databases; local servers can use "."; remote servers can be aliased on the machine, so "devserver" points to whatever the user wants.

Just a thought...

Marc Gravell
Well, we do that for testing/production.I want to be able to override connectionstrings "per developer".
Inferis
+1  A: 

Hi, I tried this once in my project for debugging purpose but could not do it, the problem (I guess, correct me if I am wrong) is on app start up the app.config gets loaded into the memory, any changes to app.config while the app is running do not get reflected.

To overcome this here's what I did, define all the connectionstrings in the app.config and then call the ones that you want when your program is running like this.

for example lets assume you defined your connectionstrings in the app.config as follows.

<connectionStrings>
    <add name="YourNameSpace.Properties.Settings.ConnectionString_1"
        connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data  
        Source=|DataDirectory|\file.mdb"
        providerName="System.Data.OleDb"/>

    <add name="YourNameSpace.Properties.Settings.ConnectionString_2"
        connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data  
        Source=|DataDirectory|\file.mdb"
        providerName="System.Data.OleDb"/>

</connectionStrings>

define as many as you want (you are debugging right :-) ) then to call those connection settings in your code do something like this:

YourNameSpace.Properties.Settings foo = new YourNameSapce.Properties.Settings();

foo.ConnectionString_1;

HTH

Best Regards

@nand

P.S: This reply is specific to C#.

Anand
A: 

This article goes into detail on the options you have: http://aspalliance.com/820

Jonathan Parker
That brings nothing new. I said I'm able to modify AppSettings, but it's connectionstrings giving me headaches.
Inferis
A: 

You could run xmlpoke in a NAnt script when installing the website.

E.g.

  1. Deploy the NAnt with the website.
  2. Create a go.bat that calls NAnt which installs the site and does xmlpoke to modify the web.config with settings based on the server name or some other parameter.
Jonathan Parker
+2  A: 

Yes it's possible, but AFAIK only via Reflection. The following code should do what you need (read below for usage):

public static string SetConnectionString(Type assemblyMember,
                                         Type settingsClass,
                                         string newConnectionString,
                                         string connectionStringKey)
{
  Type typSettings = Type.GetType(Assembly.CreateQualifiedName(assemblyMember.Assembly.FullName, settingsClass.FullName));

  if (typSettings == null)
  {
    return null;
  }

  PropertyInfo prpDefault = typSettings.GetProperty("Default", BindingFlags.Static | BindingFlags.Public);

  if (prpDefault == null)
  {
    return null;
  }

  object objSettings = prpDefault.GetValue(null, null);

  if (objSettings == null)
  {
    return null;
  }

  // the default property, this[], is actually named Item
  PropertyInfo prpItem = objSettings.GetType().GetProperty("Item", BindingFlags.Instance | BindingFlags.Public);

  if (prpItem == null)
  {
    return null;
  }

  object[] indexerName = { connectionStringKey };
  string oldConnectionString = (string)prpItem.GetValue(objSettings, indexerName);

  prpItem.SetValue(objSettings, newConnectionString, indexerName);

  return oldConnectionString;
}

assemblyMember is the calling type
settingsClass is the type of your settings class
newConnectionString is the full string to set
connectionStringKey is the name of the connection string that you defined in your app's settings

You should call this method as soon as possible after your app has started, preferably in the Main() method.

Ian Kemp
Thanks, I'll try that.
Inferis