It is just too easy to accidentally push confidential information up to a publicly hosted source repository such as Github. Also, when managing a project with multiple developers, it can become messy managing multiple configuration files between team members.
How often do you pull the latest changes down from source control, and then need to reset a database connection string after someone else accidentally pushed their own modified App.config or Web.config file up?
Even when the settings or connection strings are not critically private, this can be a pain.
Image by Rina Pitucci | Some Rights Reserved
Consider a typical Web.config file from an ASP.NET MVC web application (non-relevant content removed for clarity):
ASP.NET Web.config File Example
="1.0" ="utf-8"
-->
<configuration>
<connectionStrings>
<add name="DefaultConnection" value="YourConnectionStringAndPassword"/>
</connectionStrings>
<appSettings file="PrivateSettings.config">
<add key="owin:AppStartup" value="AspNetIdentity2ExtendingApplicationUser.Startup,AspNetIdentity2ExtendingApplicationUser" />
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="EMAIL_PASSWORD" value="YourEmailPassword"/>
</appSettings>
</configuration>
In the above, there is a database connection string we likely don't want to push to a public repo, and/or which may differ from developer to developer on a team, even internally if they are working against different or individual development versions of the application database.
Also, there is an email password, likely used to send email from within the application, which also may differ amongst team members during development, and which also should not be published publicly.
At the same time, there is a bunch of other stuff which is global to the application, so keeping the entire Web.config file out of source control is not an attractive option, either.
Fortunately, the .NET ConfigurationManager
affords us a couple of handy ways to deal with this.
We can use the configSource
attribute to move an entire Configuration Section to an external file. For example, database connection strings are one of the most common items we need to keep in our App.config or Web.config files, but which we also (usually) don't want to publish to a publicly hosted source control repository.
We can add a separate configuration file named (for example) connectionStrings.config, and then use the configSource
attribute within our Web.config file to refer to it. To do so, add a new Web Configuration file, name it ConnectionStrings.config, and then put only the following in the new file (no XML header, nothing but the <connectionStrings>
section tags, and the <add>
element(s):
ConnectionStrings.config File Example
<connectionStrings>
<add name="DefaultConnection" value="YourConnectionStringAndPassword"/>
</connectionStrings>
Then, we can modify our original Web.config file, removing the <add>
element from the <connectionStrings>
section, and instead, using the configSource
attribute to refer to the new ConnectionStrings.config file:
Modified Web.config File Using configSource:
<connectionStrings configSource="ConnectionStrings.config">
</connectionStrings>
Now, we can still access our connection string the same as always:
Accessing Connection String By Name:
var conn = ConfigurationManager.ConnectionStrings["DefaultConnection"];
string connString = conn.ConnectionString;
In the above, accessing the connection string by name like that returns a ConnectionStringSettings
object.
When we use the configSource
attribute, the Configuration Section to which it is applied can contain no actual elements. The entire section will be referred to from the external file. Note that the configSource
attribute can be used in this manner with any Configuration Section.
You may have a case, such as our example Web.config file above, in which most of the values in the <appSettings>
Configuration Section are global to the project, but also include a handful of settings which should remain private
, and kept out of source control.
In these cases, there is a special file
attribute available specifically to the <appSettings>
section which essentially allows us to extend <appSettings>
to an external file. In other words, ConfigurationManager
will recognize the contents in both locations when referring to <appSettings>
and make all transparently available within the application.
In our example case, we have an email password we would like to keep private
. We might add another Web Configuration file named PrivateSettings.config. Once again, there should be no XML header. The only thing this file should contain will be a set of <appSettings>
elements, and within those, the special settings we wish to define privately.
Special PrivateSettings.config File Extends AppSettings Section
<appSettings>
<add key="MAIL_PASSWORD" value="xspbqmurkjadteck"/>
</appSettings>
No, we remove the email password element from Web.config, and add the file attribute to the <appSettings>
section element, pointing to the new PrivateSettings.config file:
Add File Attribute to Web.config AppSettings
<appSettings file="PrivateSettings.config">
<add key="owin:AppStartup"
value="AspNetIdentity2ExtendingApplicationUser.Startup,
AspNetIdentity2ExtendingApplicationUser" />
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
Again, as before we can access any of our settings in the standard manner -
externalizing the email password setting to a separate file is transparent to
client code:
Accessing Settings:
var pwd = ConfigurationManager.AppSettings["MAIL_PASSWORD"];
Now we can add our Web.config file to source and commit, and add the two special files, ConnectionStrings.config and PrivateSettings.config to our .gitignore file, and commit away. When it's time to push to a shared repo, our private
information will stay private
.
Of course, when we take this type of approach, it will be helpful to other developers if our documentation clearly indicates what is going on here. We might do this in our project README file, and/or add some XML comments at each point in our modified Web.config informing others that they will need to add the proper files to their local version of the project, and what those files should contain.
John on GoogleCodeProject