Conditional Compilation Constants and ASP.NET

asp.net 0 comments suggest edit

UPDATE: K. Scott Allen got to the root of the problem. It turns out it was an issue of precedence. Compiler options are not additive. Specifying options in @Page override those in web.config. Read his post to find out more.

Conditional compilation constants are pretty useful for targeting your application for a particular platform, environment, etc… For example, to have code that only executes in debug mode, you can define a conditional constant named DEBUG and then do this…

#if DEBUG
//This code only runs when the app is compiled for debug
Log.EverythingAboutTheMachine();
#endif

It’s not common knowledge to me that these constants work equally well in ASPX and ASCX files. At least it wasn’t common knowledge for me. For example:

<!-- Note the space between % and # -->
<% #if DEBUG %>
<h1>DEBUG Mode!!!</h1>
<% #endif %>

The question is, where do you define these conditional constants for ASP.NET. The answer is, well it depends on whether you’re using a Website project or a Web Application project.

For a Web Site project, one option is to define it at the Page level like so…

<%@ Page CompilerOptions="/d:QUUX" %>

The nice thing about this approach is that the conditional compilation works both in the ASPX file as well as in the CodeFile, for ASP.NET Website projects.

According to this post by K. Scott Allen, you can also define conditional compilation constants in the Web.config file using the <system.codedom /> element (a direct child of the <configuration /> element, but this didn’t work for me in either website projects nor web application projects.

<system.codedom>
  <compilers>
    <compiler
      language="c#;cs;csharp" extension=".cs"
      compilerOptions="/d:MY_CONSTANT"
      type="Microsoft.CSharp.CSharpCodeProvider, 
        System, Version=2.0.0.0, Culture=neutral, 
        PublicKeyToken=b77a5c561934e089" />
    </compilers>
</system.codedom>

At heart, Web Application Projects are no different from Class Library projects so you can set conditional compilation constants from the project properties dialog in Visual Studio.ConditionalCompilation -
Microsoft Visual
Studio

Unfortunately, these only seem to work in the code behind and not within ASPX files.

Here’s a grid based on my experiments that show when and where setting conditional compilation constants seem to work in ASP.NET.

Web.config Project Properties Page Directive
Website Code File No n/a Yes
Web Application Code File No Yes No
ASPX, ASCX File No No Yes

In order to create this grid, I created a solution that includes both a Web Application project and a Website project and ran through all nine permutations. You can download the solution here if you’re interested.

It’s a bit confusing, but hopefully the above table clears things up slightly. As for setting the conditional constants in Web.config, I’m quite surprised that it didn’t work for me (yes, I set it to full trust) and assume that I must’ve made a mistake somewhere. Hopefully someone will download this solution and show me why it doesn’t work.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

12 responses

  1. Avatar for Nick
    Nick September 17th, 2007

    I would think that setting the constants in the Web.config file would only work for the front-end files. I've never played with those settings before, but I was always under the impression that the ASP.Net runtime used them when compiling the assemblies for the front-end files.

  2. Avatar for Justin M. Keyes
    Justin M. Keyes September 17th, 2007

    maybe the DEBUG symbol in ASPX/ASCX files depends on <compilation debug="true/false"> in the Web.config? (I can't test it at the moment)

  3. Avatar for Christopher Steen
    Christopher Steen September 18th, 2007

    Link Listing - September 18, 2007

  4. Avatar for Jason Monroe
    Jason Monroe September 22nd, 2007

    You can do sudo debugging checks in web site projects (vs web application projects) by checking the httpcontext. For example, for one of our websites, we've developed some custom http modules that we turn on in our model office / production environment, but off for our dev environments.
    In our dev environments, we have debugging="true" in web.config and in the others, we of course have debugging="false".
    So, when you want to check for debugging being enabled, then instead of wrapping up your code like this:

    #if DEBUG
    ... some code here
    #else
    ... some other code here
    #end if

    You would do something like this:

    if (!HttpContext.Current.IsDebuggingEnabled)
    {
    // Production mode code here
    }
    else
    {
    // Debugging Code Here
    }

    The obvious disadvantage of this method vs using compiler pre-directives is that all of your "debug" code is compiled into the final assembly. So weigh your options and go from there.

  5. Avatar for Use little words...
    Use little words... September 22nd, 2007

    Debug / Release

  6. Avatar for K. Scott Allen
    K. Scott Allen September 24th, 2007

    Phil dug up an old post of mine on conditional compilation, but defining a constant in web.config didn't...

  7. Avatar for BusinessRx Reading List
    BusinessRx Reading List September 24th, 2007

    Phil dug up an old post of mine on conditional compilation, but defining a constant in web.config didn't

  8. Avatar for Jammer
    Jammer October 12th, 2007

    So there is no way to add a 'global' build option using the #if #endif directives? What I'm reading here is that I have to modify:
    1) the Web.config file
    2) all the .ASPX files that need the @page directive.

  9. Avatar for Haacked
    Haacked October 12th, 2007

    @Jammer I wrote an update at the top of this post that addresses this issue.

  10. Avatar for Jammer
    Jammer October 13th, 2007

    Thanks, but I understand that I can do a global Web.config setting, but this is problematic for two reasons: 1)It doesn't compile out code that I don't want released and 2) Now I have to manage multiple Web.config files for the different envrionments that I need to deploy...
    The alternative @page directive are a horrible solution b/c I'll need to changes multiple files ( and double check that I got them all correct)
    For example: In one project, I was using the contitional compiler directive to store database connection strings (with user/pass) in code constants and building seperate releases to each environment. Without the ability to specify compiler directives at the project level, I'm putting these in the Web.config file, but I'm leery of storing database user/pass credentials in a flat text file that sitting on a public web server. Do you suggest a better alternative to this scenario?

  11. Avatar for Anonymous
    Anonymous November 29th, 2011

    Apparently the project build configuration doesn't affect the Web.config transformation (Web.Debug.config vs. Web.Release.config) properly in a development environment. It appears does work when you publish the project, however. A colleague said the bug was reported and Microsoft flagged it as "fixed in the next version of the product" so I guess everybody that bought <=VS2010 can go f*** themselves. A simple solution is to do the pre-processing in the code-behind file at compile-time and create a constant field. Then use your own field at run-time to conditionally enabled and disable functionality:

    #if DEBUG
    public const bool IsDebugMode = true;
    #else
    public const bool IsDebugMode = false;
    #endif


    <%
    if(this.IsDebugMode)
    {
    %>

    You get an extra paragraph because you're awesome.


    <%
    }
    %>

    It's not ideal, but at least you *know* it works.

  12. Avatar for Russian
    Russian December 21st, 2017

    Thank you for this manual!