This has happened to me more than once. You are working on a web site and are using xcopy for your deployment, whether it be xcopy from an automated process or a manual process and guess what you forgot to set the debug setting in the web.config to false. How many sites are out there with this setting? Is it that big of a deal? Recently, I discovered that not only is your site compiled for debug but also if you use Microsoft Client Side Ajax library (the Javascript included whenever you add ScriptManager tag) it will never get cached. Yes if you are in debug mode each and every visitor to your site will have to upload the entire Microsoft Ajax Client Library as it will not be cached on the client end.
This post will detail an approach to ensuring that the debug setting in the web.config is always deployed with a setting of false.
Listing 1 contains the source code for a console application. The code is extremely simple.
Listing 1
10 public class Program
11 {
12 public static void Main(string[] args)
13 {
14 //Only do this for web.config
15 if (args.Length == 1)
16 {
17 CultureInfo ci = Thread.CurrentThread.CurrentCulture;
18 string path = args[0] as string;
19 if (File.Exists(path) && Path.GetFileName(path).ToLower(ci).Equals("web.config"))
20 {
21 SetDebugTrue(path);
22 }
23 }
24 }
25
26 //Find the Compilation XML node and set it's debug attribute to false.
27 //This should be part of the build process to ensure deployed code is in
28 //release mode.
29 private static void SetDebugTrue(string path)
30 {
31 XmlDocument doc = new XmlDocument();
32 doc.Load(path);
33 XmlElement compile = doc.DocumentElement.SelectSingleNode("system.web/compilation") as XmlElement;
34 if (compile != null)
35 {
36 compile.SetAttribute("debug", "false");
37 doc.Save(path);
38 }
39 }
40
41 }
The Main accepts a parameter which contains the path of the web.config file. The debug flag is only set if the file is named web.config. The private method SetDebugTrug finds the system.web/compilation XML element and sets the debug attribute to false and that’s it. But let’s go one step further and write a unit test. In order to test this code we will need to set the Program class to public and the Main method to public. By default the Console Application template project sets both of them to internal which makes them difficult to test.
Listing 2 contains the unit test code. I am using nUnit but feel free to use whatever unit testing framework you are comfortable with.
Listing 2
12 [TestFixture]
13 public class SetDebugFalseTest
14 {
15 [Test]
16 public void Test_Debug_Attribute_In_WebConfig_Set_To_False()
17 {
18 string[] args = { "web.config" };
19 Assert.That(GetDebugFlag(), Is.EqualTo("true"),"Bad starting web.config. Try rebulding.");
20 Program.Main(args);
21 Assert.That(GetDebugFlag(), Is.EqualTo("false"));
22 }
23
24 private string GetDebugFlag()
25 {
26 XmlDocument doc = new XmlDocument();
27 doc.Load("web.config");
28 XmlElement compile = doc.DocumentElement.SelectSingleNode("system.web/compilation") as XmlElement;
29 return compile.GetAttribute("debug");
30 }
31 }
For this test to work you will need to add a web.config file, with debug set to true, to the test project and make sure that the Build Action Copy to Output Directory is set to Copy always. The unit test creates an array of string that is passed to the Main method of the Program class (from listing 1). We then assert that the debug flag is set to false.
The last step in the process is to make sure that this code is executed whenever the site is deployed. Lately, I have been using CruiseControl.NET for my continuous integration progress. Integrating the above in ccnet is quite simple. Listing 3 shows a fragment of the CruiseControl config file that is responsible for running the above code.
Listing 3
184 <exec>
185 <executable>sdf.bat</executable>
186 <baseDirectory>c:\ccnet\projects\gtanetws\src\ccnet</baseDirectory>
187 </exec>
Here I am using the ccnet exec task to run a batch file. The batch file contains a single line of code that runs the console application produced from listing 1.