Don't you just love those days when you come to work full of energy and ideas, ready to have a productive day only to be stumped by a seemingly simple problem that ends up wasting the entire day? Today was one of those days. My only consolation is that this blog post reports the solution, hopefully saving some other poor soul their time and their sanity.
The need was simple. Write out connection strings to the app.config file of an application and encrypt them. Sound easy? Sure. There are lots of examples out there about how to do this, but there's a problem no one seems to mention. You can't just update a config file at runtime and expect those changes to stick. I ran into that problem the other day and solved it here. But there's a more sinister problem. Let me explain.
First, here's what I'm doing:
I have an array of connection strings (as strings) from an external service that I want to add to the app.config file of the current application. I write them out to the <connectionStrings> section and then save the file, taking care to make sure I tell the System.Configuration.ConfigurationManager to refresh the section, meaning it should reload the section from disk the next time it's accessed.
When this happens further along in the program on this line ...
ConnectionStringSettings dbConn = System.Configuration.ConfigurationManager.ConnectionStrings[DefaultDatabaseKey];
... I get this error message:
Unrecognized attribute 'configProtectionProvider'.
I did the usual searches and came up with no solutions. Some folks suggested loading two AppDomains, restarting the app, etc. I can't believe you'd have to restart an app just to pick up configuration changes! After all, I can to this now. The problem comes when I try to encrypt the section.
When you successfully encrpyt a section, a new attribute "configProtectionProvider" is added to the <connectionStrings> element. It appears that when ConfigurationManager tries to reload this section, it can't digest this new attribute.
Okay, let's just get to the solution before I waste even more of my day...
The answer turned out to be simple. Instead of telling ConfigurationManager to refresh the "connectionStrings" section, have it refresh the next level up which would be the <configuration> section itself:
Oh happy day.