ASP.NET Create a Debug Build Checker page for your Site

There are two things you absolutely want to be sure and avoid for a production ASP.NET site: 1.) Leaving the <compilation debug="true"/> switch on within the application’s web.config file, and 2.) Deploying assemblies that have been built in debug configuration mode.

If you do one or both of the above it can cause a number of non-optimal things to happen including:

1) The compilation of ASP.NET pages takes longer (since some batch optimizations are disabled)
2) Code can execute slower (since some additional debug paths are enabled)
3) Much more memory is used within the application at runtime
4) Scripts and images downloaded from the WebResources.axd handler are not cached
5) When debug is set to true, asp.net requests will not time out. This is for easier debugging but you don't want it in production!

If you have debug=true, you create one assembly dll per aspx, asax, or ascx page and this dll is compiled in debug mode, so if you have 100 web pages, you will have 100 assemblies, and they are generated as the pages are requested.

With debug=false, everything gets batch compiled into a single assembly (with some exceptions). This means less overhead in your app.

So how can you be sure that your deployed app is OK without having to jump through hoops? I've created a simple "script only" (no codebehind) page that you can drop into any production web app. It will report any debug-built assemblies, and also will report on the setting of your compilation element in web.config to let you know if debug=true or debug=false.

To get an understanding of how I engineered this, we need to look at the differences between release build and debug build assemblies as shown in Reflector:


DEBUG
// Assembly debugcheck, Version 1.0.0.0

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyTitle("debugcheck")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("debugcheck")]
[assembly: AssemblyCopyright("Copyright \x00a9 Microsoft 2011")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("18ee114d-54a6-43c3-8613-29dd338c7adb")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName=".NET Framework 4")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.EnableEditAndContinue | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.Default)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows=true)]


RELEASE
// Assembly debugcheck, Version 1.0.0.0

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyTitle("debugcheck")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("debugcheck")]
[assembly: AssemblyCopyright("Copyright \x00a9 Microsoft 2011")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("18ee114d-54a6-43c3-8613-29dd338c7adb")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName=".NET Framework 4")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows=true)]

In both the release build and debug build, the IgnoreSymbolSequencePoints DebuggingModes flag will be present. However, in a debug build, the DisableOptimizations attribute will also be present. This is necessary because optimizations result in code rearrangement in the output file, which can make debugging difficult. Optimization is normally disabled while debugging.

The HttpContext.Current.IsDebuggingEnabled property seen below actually reads the <compilation.. debug attribute from your web.config file.

You can copy all the code that follows, paste it into a text file and save it as DebugBuild.aspx and you are "good to go". Just drop it into any web application, and request the page to see the state of your app.

<%@ Page Language="C#" AutoEventWireup="true"  %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Web.Configuration" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>DEbug Build Checker</title>
    <script runat=server language="C#">
        protected void Page_Load( object sender, EventArgs e)
         {
             DoDebugCheck();
        }

    public class  Info
    {
         public string AssemblyName { get; set; }
         public bool IsDebug { get; set; }
    }

         private bool IsAssemblyDebugBuild(string filepath)
         {
             return IsAssemblyDebugBuild(Assembly.LoadFile(Path.GetFullPath(filepath)));
         }
         
        private bool IsAssemblyDebugBuild(Assembly assembly)
        {
            foreach (var attribute in assembly.GetCustomAttributes(false))
            {
                var debuggableAttribute = attribute as DebuggableAttribute;
// if IgnoreSymbolStoreSequencePoints and DisableOptimizations flags are both present, the assembly was built in debug mode
                 if (debuggableAttribute != null)
                 {
                     return
                        debuggableAttribute.DebuggingFlags.HasFlag(
                            DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints) &&
                          debuggableAttribute.DebuggingFlags.HasFlag(
                              DebuggableAttribute.DebuggingModes.DisableOptimizations);
                 }
             }
             return false;
        }

         private void DoDebugCheck()
        {
            var infos = new List<Info>();

            string path = Server.MapPath("~/") + @"\bin\";
            
                var di = new DirectoryInfo(path);
                FileInfo[] files = di.GetFiles();
                foreach(FileInfo fi in files)
                 {
                     if(  (fi.Name.ToLower().Contains(".dll") || fi.Name.ToLower().Contains(".exe")) &&
                        (!fi.Name.ToLower( ).Contains(".config") && !fi.Name.ToLower( ).Contains(".manifest")) )
                    {
                        string name = fi.Name;
                        bool isDebug = IsAssemblyDebugBuild(Path.Combine(path, fi.Name));
                          if (isDebug)
                        {
                            var ai = new Info() {IsDebug = isDebug, AssemblyName = name};
                              infos.Add(ai);
                         }
                     }
                 }
                  this.GridView1.DataSource = infos;
             GridView1.DataBind();
             if (infos.Count == 0)
                label1.Text = "No Debug Build Assemblies found.";
            label1.Text += "<br/>Web.Config Debug Setting = " + HttpContext.Current.IsDebuggingEnabled.ToString();
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <h1>DEBUG BUILD CHECKER</h1>
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns=true>
        </asp:GridView>
    <asp:Label id=label1 runat=server />
    </div>
    </form>
</body>
</html>

Get in the habit of requesting this page after every deployment. If you don't see this:


DEBUG BUILD CHECKER

No Debug Build Assemblies found.
Web.Config Debug Setting = False

-- Then you have a problem!

By Peter Bromberg   Popularity  (3123 Views)