Articles by Upendo Ventures

We "Upendo" to Write for You!

Our team loves to share our thoughts, research, experiences here in our blog. Please enjoy our articles and leave a comment to let us know what you think.

Super Useful web.config Trick for Development Teams

Upendo Ventures: Super Useful web.config Trick for Development Teams

Every ASP.NET application has no less than one website configuration file - also called the web.config, since that’s what the name of the file actually is. We often get asked a lot of questions about how to properly check-in the web.config and how to safely distribute the file across environments and developers. This article is going to disclose one of the tricks that we use for our clients. 

What is the web.config Anyway?

This is simply a configuration file that provides detailed configuration information that ASP.NET, IIS, and the webserver need to successfully load and run your website application. 

The file itself usually contains a ton of configuration information for the website application, as you might imagine. The one in the root folder of your website application contains the majority of the configuration details you need to know about. Any others usually just override the main configuration file for that specific folder. 

When it comes to the web.config, you definitely don’t want to lose it and the details it contains. Doing so will almost always be detrimental to your website application. Over time, this file will become quite verbose and recreating it is nearly impossible unless you have a backup of it. 

What’s more, is that you’re almost certainly going to have more than one copy of your website in various places around the server room, office, and various developers across the world. The versions of your website may include staging, UAT, testing, and another one for each developer that writes code for your website. Even your testing team, if you have one, will likely have a local copy of the source code of your website to properly test updates before they get deployed into other environments.  

You might be thinking, now, "How in the world do I safely keep track of that across every single environment?" It’s an outstanding question. It only takes a single developer making a change to the web.config to get the website working in their own development environment before the risk of it getting accidentally deployed into your testing, staging, and production environments. 

Can I Commit the web.config to Source Control?

The short answer is generally yes, but this presents a ton of complications moving forward. Every environment where the web.config is restored to and used in will require slightly different versions to be in place. In the very least, your database connection strings will need to be different. So, committing this file to source control is something that needs to be done carefully. 

When it comes to the information in the web.config, most use cases will determine that the majority of the configuration details be the same from environment to environment. 

How Can I Make the web.config Safe to Commit to Source Control?

The answer is surprisingly simple and elegant. It’s also a built-in feature that any ASP.NET application can take advantage of. Most of this is inspired by a blog post by the one and only, Scott Hanselman

First, you need to identify the sections that need to be unique per environment. Then, you need to come up with a common pattern for your development, testing, and deployment teams. 

In the case of DNN-based websites, there are two sections that tend to be the most unique in each environment. They are the <connectionStrings> and <appSettings> sections. 

The <connectionStrings> section probably sounds self-explanatory. Every instance of the website will likely require a different database connection string for each database connection the application needs. 

The <appSettings> section contains global settings for the application. While much of it will be the same across deployment locations and environments, there tends to be one or more values that need to be different in each location the website runs from. This may also include legacy connection strings, API details for external systems that are integrated, and nearly anything else. 

Updating the web.config for Multiple Environments

Since we’ve identified the <connectionStrings> and <appSettings> sections in our example, we’ll continue to work with that. A development pattern that we’ve found to work fairly universally so far is to add two new files to the App_Data folder. (If your application doesn’t have this folder, create it. It’s a protected application folder for ASP.NET websites.)

Create the following two files in your App_Data folder (note that they’re still .config files, for security purposes):

  • appSettings.local.config
  • connectionStrings.local.config

The naming convention you see above is as follows:

  1. Section name as it’s seen in the web.config
  2. Environmental context (e.g., a local-only configuration)
  3. Configuration file extension

In each file, you’ll want to add the respective section from your original web.config file. An example of the contents of your connection strings configuration file may look like the code example below.

<connectionStrings>
  <add name="SiteSqlServer" connectionString="Data Source=(localhost);Initial Catalog=MYDATABASE;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>

Your application settings may look like this example:

<appSettings>
  <add key="InstallTemplate" value="DotNetNuke.install.config" />
    <add key="AutoUpgrade" value="false" />
    <add key="UseInstallWizard" value="true" />
    <add key="InstallMemberRole" value="true" />
    <add key="ShowMissingKeys" value="false" />
    <add key="EnableCachePersistence" value="false" />
    <add key="HostHeader" value="" />
    <add key="RemoveAngleBrackets" value="false" />
    <add key="PersistentCookieTimeout" value="0" />
    <add key="EnableServicesFrameworkTracing" value="false" />
    <add key="UpdateServiceUrl" value="https://dnnplatform.io" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="loginUrl" value="~/Login.aspx" />
    <add key="ValidationSettings:UnobtrusiveValidationMode" value="None" />
    <add key="ImprovementProgram.Endpoint" value="https://dnnapi.com/beacon" />
    <add key="InstallationDate" value="12/13/2019" />
    <add key="InstallVersion" value="09.04.04" />
    <!-- additional values omitted from this code sample -->
</appSettings>

Next, you’ll need to update your web.config file to (1) remove the original section, and (2) point to the new location, at the same time. The example below shows what that looks like. 

<connectionStrings configSource="App_Data\connectionStrings.local.config" />
<appSettings configSource="App_Data\appSettings.local.config" />

That’s it, from the highest level. If the website was already successfully running, you can save all of these files and run the website to verify it’s working right away.  (It’s worth noting that you can mix the values between the local config files and the root web.config, but we’re trying to keep the code samples simple here.)

You can now safely begin committing the web.config into source control. From this point forward, every commit to the web.config should reflect changes that are required across every instance where the website runs, just like any other code updates you might be working on. 

Update the .gitignore File

(This is obviously assuming you’re using Git for source control...)

Now that you’ve safely updated the web.config for distributed teams and environments, you may need to update your .gitignore file to allow the web.config file to be committed, if it’s not already being done. 

Another update you’ll need to do now, though, is to update it to also ignore the new local instances of the configuration files we just created. This may look like the following example:

# local configuration files
*.local.config

Update your README for Default Values

When you have new developers, testers, and consultants come aboard, they’re going to need to set-up their own environments successfully. So don’t forget to update your solution’s README and/or your organization’s developer documentation to help them know how to get started with a newly restored environment. They need to add the local configuration files with the correct details that everyone else has. 

You can, of course, have existing developers send their respective copies of the local configuration files, but it would be much more secure and consistent with processes if they were to get those from a secured and safe location in your organization, such as your intranet/extranet, or a shared secure file-sharing server.  Anything requiring at least one-level of authentication will do.  

As any of the default values change, you’ll need to ask all stakeholders to update their local copies.  When this occurs, you should just point them to the centralized location where the default values are maintained to keep things streamlined and secured. 

Closing Summary

It really is that simple. How do you do this in your own projects and teams? Do you have similar tricks, or do you do something else entirely? Let’s chat about it in the comments below. 

Contact Us
Let’s Chat!

We’d love to work with you. Let’s talk about how.

Contact Us


About the Author

Will StrohlFounder & CEO
Upendo Ventures
Overall, Will has nearly 20 years of experience helping website owners become more successful in all areas, including mentoring, website development, marketing, strategy, e-commerce, and more.

blog comments powered by Disqus