Conditional Compilation Constants and ASP.NET

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.

What others have said

Requesting Gravatar... Jason Haley Sep 17, 2007 7:10 AM
# Interesting Finds: September 17, 2007
Requesting Gravatar... Nick Sep 17, 2007 1:39 PM
# re: Conditional Compilation Constants and ASP.NET
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.
Requesting Gravatar... Justin M. Keyes Sep 17, 2007 3:59 PM
# re: Conditional Compilation Constants and ASP.NET
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)
Requesting Gravatar... Christopher Steen Sep 19, 2007 3:44 AM
# Link Listing - September 18, 2007
Link Listing - September 18, 2007
Requesting Gravatar... Jason Monroe Sep 23, 2007 8:17 AM
# re: Conditional Compilation Constants and ASP.NET
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.
Requesting Gravatar... Use little words... Sep 23, 2007 8:42 AM
# Debug / Release
Debug / Release
Requesting Gravatar... K. Scott Allen Sep 24, 2007 8:37 PM
# More on Conditional Compilation in ASP.NET
Phil dug up an old post of mine on conditional compilation, but defining a constant in web.config didn't...
Requesting Gravatar... BusinessRx Reading List Sep 24, 2007 8:48 PM
# More on Conditional Compilation in ASP.NET
Phil dug up an old post of mine on conditional compilation, but defining a constant in web.config didn't
Requesting Gravatar... Jammer Oct 12, 2007 3:07 PM
# re: Conditional Compilation Constants and ASP.NET
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.

Requesting Gravatar... Haacked Oct 12, 2007 4:07 PM
# re: Conditional Compilation Constants and ASP.NET
@Jammer I wrote an update at the top of this post that addresses this issue.
Requesting Gravatar... Jammer Oct 14, 2007 8:43 AM
# re: Conditional Compilation Constants and ASP.NET
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?

What do you have to say?

(will show your gravatar)
Please add 2 and 4 and type the answer here: