(Or why are there no variables in .Net’s Web.config)

The .net web.config file is kind of a pain when working with source control and multiple developers. I’ve been trying to figure out the best way to keep conflicts to a minimum, and allow for each developer to have different configurations (which is required for the current development environments).

So here is the crux of the problem. There are user defined setting in that file that look like this:

<appSettings>
...       <add key="OLAPCString" value="Provider=MSOLAP; Integrated Security=IIII; Data Source=QRSTUV;Initial Catalog=WXYZ;Cube Name=ABCD;"/>
...
</appSettings>
<connectionStrings>
...       <add name="ConnectionString" connectionString="Server=127.0.0.1;Database=TheDB;uid=TheUID;pwd=ThePWD;Max Pool Size=100; Connect Timeout=300;"/>
...
</connectionStrings>

There are many settings in both appSettings and connectionStrings that need to change based on the developers environment, but we also want to have a base version.

Setting it up with the developers directly adding / editing web.config will have web.config conflicting constantly. Often daily, eating into development time. As people add things to the file other developers will have to readjust the connection strings etc for their own environment. It gets really old really fast.

appSettings has an attribute “file” that lets you specify an external file that can override settings in the appSetting section - which is great. If that file exists, and a setting is defined there it uses that one, if the setting is not overwritten it uses the default one web.config.

That’s great, and solves half the problem, but what about connectionStrings? Well, there is an attribute “configSource” which allows you to have an external file but it’s an either or choice. You either define something in web.config or in an external file - it doesn’t override like in appSettings.

I am left scratching my head as to why that would be. It doesn’t make any sense. Why can’t you do the same thing as with appSettings (Well, Rob, because it simply is that way - he said to himself).

So, from what I can tell, we either:

1. Leave the connection strings in web.config and get svn conflicts

2. Move them to an external file, put the external file in svn and still get conflicts

3. Move to an external file, put a comment in the web.config and if someone adds something to connectionStrings (or we get new developers) have them add it to that comment and tell the developers to add it to their local file.

This seems overly complicated.

I tried to dance around this by doing something like the following on startup:

//get the developer defined connection string
string connectionString = ConfigurationManager.AppSettings.Get("ConnectionString");
//set the "real" connection string
WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString = connectionString;

but, of course, the connectionStrings connection string is readonly. Sigh.

I even tried adding entity references to the web.config in order to get around it:

<?xml version="1.0" standalone="yes" ?>
<!DOCTYPE configuration [
<!ENTITY server "192.168.1.100">
]><configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
...

But that doesn’t work either for several reasons (I even tried to find a version of the schema to try to use a hacked version, but I couldn’t find one).

Square peg round hole.

Anyway, until we are enlightened, we’ve just decided to do the override for appSettings and just “waste” time dealing with the inevitable connectionStrings conflicts.

Anyone have any suggestions? Or is just a limitation of .Net development?

(On a positive note, the ability to completely override these sections, the configSource setting, makes doing deploys quite nice)

Comments

This entry was posted on Friday, April 11th, 2008 at 1:32 pm and is filed under Web Apps, Windows. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.

7 Comments so far

  1. alphalpha noober on April 14, 2008 7:57 am

    My suggestion is not use .Net

    .Net is like a 2 dollar whore, you only call on her when your really need a piece of ass.

  2. 小罗 on April 14, 2008 12:10 pm

    Hehehe. Wow, uh, thanks alphalpha, but a full re-write of the application is kind of out of the question at this point.

  3. Juicy Lucy on May 5, 2008 11:20 am

    Why not just simply use the the connection string as just another app setting?

    You will need to use ConfigurationManager.AppSettings(”ConnectionString_1″) instead of ConfigurationManager.ConnectionString(”ConnectionString_1″)

    I know it is not the cleanest way to do it but it works.
    Hope this helps.

  4. 小罗 on May 5, 2008 11:30 am

    Hi Lucy, Thanks for the comment.

    The reason that wont work is because the project uses 3rd party components that use the connection string setting :(

  5. Daniel on July 28, 2008 7:13 am

    This is a little late, but the recommended way to do this in svn is to create a “template” essentially. Version the template file, which is basically a config file with all defaults. Then set the real config to be ignored. So you’ll have a file called web.config.defaults that is checked in, and a file called web.config which would always be ignored.

    Developers can then copy web.config.defaults and rename it to web.config, add their customizations which never get checked in. If new defaults need to be added, they’d have to be added to web.config.defaults.

    You can also use the template strategy for different components, using the configSource attribute, so you can keep your connection strings in a separate file, and have a connectionStrings.config.defaults file for example.

    I still think this is a major screw-up on the part of MS. The appSettings file attribute works great because it’s overridable, but it’s only available for that particular element and not for connection strings. Argh.

  6. 小罗 on July 28, 2008 8:21 am

    Thanks for the input Daniel - it’s never too late :-D

    We wound up doing something similar to what you’re suggesting (just with different file names). It’s good to hear we weren’t too far off

  7. Paul Houle on August 27, 2008 12:41 pm

    I’m facing this problem right now. For a while, we used the “connection string manager” built into the ASP.NET configuration tool you can access from the IIS Manager.

    You can set global configuration settings, or you can set configuration settings for a directory… In that case, the automatic manager writes them into a Web.config at that level: this points to a more manual way to do it…

    C:/Inetpub/wwwroot/Web.Config <– developer’s private Web.Config
    C:/Inetpub/wwwroot/yourApplication/Web.Config <— general Web.Config

    Make sure the handful of special properties in the developer’s config aren’t defined in the global config, and you’re doing great.

    For the app I’m working on now, we’ve got an installer that copies the app from our Visual Studio project into a directory on the server: it’s called in the post-build, so developers hardly ever need to think about it. The installer can make string substitutions in the Web.config, so it’s easy to have developer-specific config files.

Name (required)
Email (required)
Website
Share your wisdom