Introduction
Most systems developed would have different environments; to name a few, Development (Dev), Quality Assurance (QA), or Testing and Live or Production. This article describes how to incorporate all three environment configurations without having to change them while deploying.
Background
Many of us have developed applications using Connection String settings in a configuration file, either web.config or app.config. This, in turn, has to be deployed in the different environments listed above. For the application to work in a particular environment, we then have to make changes to this setting. This process has to be repeated for each and every release. The luxury of keeping the config files constant does not arise as more and more settings keep adding to the configuration every iteration or the other. If this has to be done over many such settings, we indeed have a problem.
This article addresses this issue, and is primarily meant for architects or technical leads who develop frameworks from which applications are built.
Using the code
This can be readily used in the Business Logic Layer of systems implementing an N-Tier architecture. The AppConfiguration
class (attached source) to obtain the configuration value should be part of the core module of the framework. All code to access the configuration should make use of this class. For other systems, a workaround is required. Be prepared to make sacrifices as most of the VS2005 code generators don't anticipate this scenario, but the benefits far outweigh these sacrifices.
This works for both types of configuration files: Web.config or App.config. For the sake of clarity, any reference to configuration file would indicate either of them.
To implement this, we need to add a <switches>
node under the <system.diagnostics>
node to the configuration file.
<configuration>
<system.diagnostics>
<switches>
<add name="Debug" value="0"/>
<add name="DevMode" value="1"/>
<add name="QAMode" value="0"/>
<add name="LiveMode" value="0"/>
</switches>
</system.diagnostics>
</configuration>
Here, four switches are added which are of identical nature. These have been subdivided into two sections: Trace Switch and Boolean Switch. The switches "DevMode
", "QAMode
", and "LiveMode
" each indicate different environments, and as the comment points out, only one environment can be active among them. The distinction of transformation to a specific switch type can be understood in combination with the code declaration.
Here is the code declaration to activate and transform these switches. Please note: the names of switches should match the declaration.
using System.Diagnostics;
public static TraceSwitch DebugSwitch = new TraceSwitch("Debug", "Debug mode");
public static BooleanSwitch DevModeSwitch = new BooleanSwitch("DevMode",
"Identifies Development Mode");
public static BooleanSwitch QAModeSwitch = new BooleanSwitch("QAMode",
"Identifies Quality Assurance Mode");
public static BooleanSwitch LiveModeSwitch = new BooleanSwitch("LiveMode",
"Identifies Live Mode");
After having done the initial declarations, the settings entry needs to be made. Only the <appSettings>
node can be used. Instead of having a single entry, settings specific to each environment is made. Here, three entries are made for each setting: one each for Dev, QA, and Live. The settings have a suffix "_Dev", "_QA", and none, respectively, for each of these environments.
<configuration>
<appSettings>
<add key="ConnectionString"
value="server=192.168.100.3;database=Database_Live;uid=liveUser;pwd=livePassword;"/>
<add key="ConnectionString_QA"
value="server=192.168.100.2;database=Database_QA;uid=qaUser;pwd=qaPassword;"/>
<add key="ConnectionString_Dev"
value="server=192.168.100.1;database=Database_Dev;uid=devUser;pwd=devPassword;"/>
<add key="User_TimeOut" value="50"/>
<add key="User_TimeOut_QA" value="30"/>
<add key="User_TimeOut_Dev" value="10"/>
The logic for obtaining which setting to use is done with code in combination with both the switch and appSettings
. It's not necessary to have all settings in this format. If the settings do not change for the environments, you can opt not to use the switch and have a single entry.
using System.Configuration;
public static string GetAppSetting(string key)
{
try
{
string returnValue = String.Empty;
returnValue = GetAppSetting(key, true);
return returnValue;
}
catch
{
throw;
}
}
public static string GetAppSetting(string key, bool useModeSwitch)
{
try
{
string returnValue = String.Empty;
if (useModeSwitch)
{
if (DevModeSwitch.Enabled)
{
key += "_Dev";
}
else if (QAModeSwitch.Enabled)
{
key += "_QA";
}
}
returnValue = ConfigurationManager.AppSettings[key];
return returnValue;
}
catch
{
throw;
}
}
Here are some uses of the Trace Switch. You can use Trace.Warn
to write debug information on a Live environment after enabling tracing, or you can use Debug.Write
to output messages in a Development environment without having to set breakpoints.
if(DebugSwitch.TraceError)
{
Debug.Write("Error Line \n");
Trace.Warn("Error in Trace");
}
if(DebugSwitch.TraceInfo)
{
Debug.Write("\tHi give me a detailed info of the things to come");
Trace.Warn("Info in Trace");
}
Points to note
- Since the configuration files are for the entire application, try to break module specific settings in a configuration file of its own and write custom configuration files. Add this module configuration file path to the application configuration file as a setting, and read values from it.
- The Web Services designer adds a single entry to the web.config for dynamic requests. To recreate this scenario, you need to edit the generated proxy class file to incorporate this scenario. Unfortunately, this gets lost when you rebuild the Web Service reference. Maybe in a future version of Visual Studio, for creating a Web Service proxy class, the logic of choosing the URL would be left to the developer.
History
- 26 June 2007: Initial version.