261

I am writing my first Razor page today, and can't figure out how to enter

#if debug
...
#else
...
#endif

How can I do that in Razor?

janw
  • 8,758
  • 11
  • 40
  • 62
mamu
  • 12,184
  • 19
  • 69
  • 92
  • possible duplicate of http://stackoverflow.com/questions/378982/is-there-an-if-debug-for-asp-net-markup – Handcraftsman Jan 14 '11 at 21:46
  • 11
    My point is that you want `#if debug` in razor but it will **always** be true. So the answer to your question is that there's no point in doing it as Razor will always compile in debug mode. – Buildstarted Jan 18 '11 at 21:09

10 Answers10

409

I just created an extension method:

public static bool IsDebug(this HtmlHelper htmlHelper)
{
#if DEBUG
      return true;
#else
      return false;
#endif
}

Then used it in my views like so:

<section id="sidebar">
     @Html.Partial("_Connect")
     @if (!Html.IsDebug())
     { 
         @Html.Partial("_Ads")
     }
     <hr />
     @RenderSection("Sidebar", required: false)
</section>

Since the helper is compiled with the DEBUG/RELEASE symbol, it works.

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
Shawn Wildermuth
  • 7,318
  • 3
  • 23
  • 28
  • 36
    Of course this extension method has to go into the MVC project, not into a separate library that might be compiled with different options... – Eric J. Jul 27 '12 at 01:19
  • 3
    This didn't work for me at all- it produced "True" regardless of compilation mode. Jordan Gray's answer worked perfectly. – Timothy Kanski Feb 09 '17 at 16:14
  • If it's DEBUG mode, the pre-processor will essentially read `public static bool IsDebug(...){ return true; }`, and vice versa for non DEBUG mode. – mekb Aug 07 '19 at 09:46
  • This worked for me with a slight tweak for .Net Core: Had to change HtmlHelper to IHtmlHelper. Hope that helps someone. – Rob Dec 01 '21 at 14:23
325

This is built in to HttpContext:

@if (HttpContext.Current.IsDebuggingEnabled)
{
    // Means that debug="true" in Web.config
}

IMO, this makes more sense than conditional compilation for views and comes in handy for some testing scenarios. (See Tony Wall's comment below.)


Side note: NullReferenceException for HttpContext.Current

Alex Angas mentioned that they get a NullReferenceException with this solution, and a few people have upvoted indicating that this may not be an isolated event.

My best guess: HttpContext.Current is stored in CallContext, meaning it is only accessible by the thread that handles the incoming HTTP request. If your views are being rendered on a different thread (perhaps some solutions for precompiled views?) you would get a null value for HttpContext.Current.

If you get this error, please let me know in the comments and mention if you are using precompiled views or anything special set up that could result in your views being partially rendered/executed on another thread!

Jordan Gray
  • 16,306
  • 3
  • 53
  • 69
  • 2
    Has the advantage you can switch it on in integration test environments to diagnose deployment issues often not seen until installed on non-developer PCs. – Tony Wall Jun 03 '13 at 11:36
  • 2
    I get a null reference exception using this, probably because in Release mode the debug attribute is removed from web.config entirely. – Alex Angas Feb 27 '14 at 03:55
  • @AlexAngas Eugh, that's extremely unpleasant—thanks for mentioning it. I'll try to get a repro later and update my answer. If it throws an exception, I'll report it as a framework bug—it should return false rather than throwing an exception if the attribute isn't present! – Jordan Gray Feb 27 '14 at 11:58
  • 1
    @AlexAngas Can't repro. :( I created a project in .NET 4.5.1 (ASP.NET MVC 5, `System.Web` version 4.0.0.0), and even with the `debug` attribute (or, indeed, the whole `compilation` element) removed I don't get an exception. My next best hypotheses are that this is a bug that was fixed in later versions of the `System.Web` assembly or that there is something different about your specific situation that I'm not aware of. Could you create a minimal test project and upload it somewhere? – Jordan Gray Mar 11 '14 at 14:06
  • 4
    @JordanGray Thanks for taking a look - I just tried a new project as well and can't repro either! Your solution is working. No time to look further at the moment unfortunately but if I come across the reason i'll update this post. – Alex Angas Mar 13 '14 at 01:07
  • 6
    Bloody brilliant mate; this should be the OPs answer. – Shawn J. Molloy Sep 26 '14 at 01:45
  • 1
    This solution doesn't answer a qestion `How can i enter preprocessor in razor?` as it only handles Release/Debug but not any other conditional compilation symbol. For instance QA, Staging, Production, etc. – mdonatas Sep 29 '17 at 14:44
  • @mdonatas Correct—as I read it, the question is about differentiating debug vs release, and this is the most appropriate to check that. I recommend Shawn's answer if you need to test other compilation symbols! :) – Jordan Gray Oct 02 '17 at 01:41
  • Always rendered true for me, despite being complied for release. – CountMurphy Dec 08 '17 at 19:40
  • @CountMurphy That's odd! Sorry this is a bit late, but do you have different values in your debug/release Web.config for the `compilation` element? Specifically, in your debug config, you need to have `debug="true"` for this to work. – Jordan Gray Dec 25 '17 at 00:14
  • 1
    @AlexAngas Know it's an old comment, but I had another think about your problem and realised there's an obvious possible cause. Thanks for being the first person to let me know or I wouldn't have considered it! (BTW, I've referred to you as "they," but let me know your preferred pronouns and I'll update.) – Jordan Gray Aug 08 '18 at 12:10
24

C# and ASP.NET MVC: Using #if directive in a view

Actually that answer has the right answer. You're going to have to pass whether or not you're in debug mode via the Model. (or ViewBag) since all views are compiled in debug mode.

Community
  • 1
  • 1
Buildstarted
  • 26,529
  • 10
  • 84
  • 95
  • 27
    Note that because Razor views are always compiled in Debug mode setting a preprocessor directive in this way will not actually have any effect. You will always execute `// your debug stuff` – marcind Jan 14 '11 at 23:07
  • 1
    Heh, yeah, I just realized that when I wrote it. – Buildstarted Jan 14 '11 at 23:07
23

In .NET Core, you can use the environment tag helper instead of checking the preprocessor variables:

<environment include="Development">
    <!--Debug code here-->
</environment>
janw
  • 8,758
  • 11
  • 40
  • 62
beleester
  • 394
  • 3
  • 8
  • Microsoft also recommends this approach to include resource bundles in non-development environments: https://learn.microsoft.com/en-us/aspnet/core/client-side/bundling-and-minification?tabs=visual-studio%2Caspnetcore2x&view=aspnetcore-7.0#environment-based-bundling-and-minification – Matt May 19 '23 at 20:46
20

My solution is very stupid, but it works. Define a global constant somewhere in a static file:

public static class AppConstants
{
#if DEBUG
        public const bool IS_DEBUG = true;
#else
        public const bool IS_DEBUG = false;
#endif
}

Then use it with Razor in HTML:

@if (AppConstants.IS_DEBUG)
{
    <h3>Debug mode</h3>
}
else
{
    <h3>Release mode</h3>
}
tedebus
  • 978
  • 13
  • 20
  • imho, it's not that stupid. in debug I want to use the es6-javascript (so I see the es6-errors while developing) and in release I want to use the auto-converted non-es6-javascript (cuz IE11 doesn't know es6). this is a great solution for me. – Matthias Burger Sep 13 '19 at 07:52
  • nice one - simple direct, unambiguous – Serexx Jan 10 '20 at 17:49
  • Love it...I have a global static class for appSetting...this plugs in nicely. – Chris Catignani Apr 27 '21 at 21:11
  • I'm having a problem with this solution where it works in a Debug build, but get "AppConstants doesn't exist in this context" in a Release build. Any ideas? – Greg Barth Sep 02 '21 at 14:00
  • My guess is that you deleted the reference "@using ..." in the Razor page (relative to AppConstants namespace). Or you could have put under "#if DEBUG" the whole AppConstants declaration. – tedebus Sep 02 '21 at 15:03
  • I got it to work by saying `if (AppConstants.IS_DEBUG == true)` instead of `if (AppConstants.IS_DEBUG)`. – Greg Barth Sep 02 '21 at 15:38
  • It should be the same... "AppConstants.IS_DEBUG == true" is always true in debug because AppConstants.IS_DEBUG is declared as a const boolean (true). Visual Studio or other IDE should tell you to remove "==true" as a hint. Anyway, the important thing is that it works! ;) – tedebus Sep 02 '21 at 16:01
15

I know this is not a direct answer to the question but as I'm pretty sure debug configuration is corollary to the fact that you are actually executing locally, you can always use the Request.IsLocal property as a debug like test. Thus :

@if (Request.IsLocal)
{
    <link rel="stylesheet" type="text/css" href="~/css/compiled/complete.css">
}
else
{
    <link rel="stylesheet" type="text/css" href="~/css/compiled/complete.min.css">
}
Sbu
  • 910
  • 11
  • 22
  • 1
    Not necessarily. You might run in Debug mode on a test/development server, for example, before compiling in Release mode on Staging/Production. – jonnybot Apr 22 '16 at 15:42
  • An html helper extension method to render the link tag will help in this case. Inside the extension method you can either use #if DEBUG or a config variable to decide the environment. – sree Nov 24 '16 at 03:15
12

This works for me in a .NET Core 3.0 white label project:

@{
#if CORPA
}
    <button type="button" class="btn btn-warning">A Button</button>
@{
#else
}
    <p>Nothing to see here</p>
@{
#endif
}
janw
  • 8,758
  • 11
  • 40
  • 62
Perry Armstrong
  • 121
  • 1
  • 2
5

By default MVC views are not compiled so #IF DEBUG can't work in a view. If you want to compile view in order to access IF DEBUG config, you need to :

  1. Right click on your project in Visual Studio
  2. Unload project
  3. Edit project

change the following attribute from false to true

<MvcBuildViews>true</MvcBuildViews>

reload your project and then views are going to be compiled.

The only other work around would be to have a function in your code behind

public static Boolean DEBUG(this System.Web.Mvc.WebViewPage page)
{
   var value = false;
   #if(DEBUG)
       value=true;
   #endif
   return value;
}

and then call it from view :

if(DEBUG())
{
  //debug code here
}
else
{
  //release code here
}
Yannick Richard
  • 1,219
  • 15
  • 25
5

For me, the code below has worked very well.

When the application is Debugging my buttons appear, when is Release, they don't.

@if (this.Context.IsDebuggingEnabled)
{
    <button type="button" class="btn btn-warning">Fill file</button>
    <button type="button" class="btn btn-info">Export file</button>
} 
E.Z
  • 1,958
  • 1
  • 18
  • 27
3

I needed something similar that works in the <script> tag as well, and found that the following works well for either conditional markup in the DOM, or a conditional script.

@{
#if NOEXTAUTH
{
    @:<!-- A single line of code -->

    <text>
        <!--
        A multi-line block    
        -->
    </text>
}
#endif
}
Mr Moose
  • 5,946
  • 7
  • 34
  • 69
  • 2
    All other answers completely missed the point. In every other answer there is STILL an “if” which will go in release and will be executed. This one is the best answer. – Jurion May 27 '21 at 22:36
  • Where do you define NOEXTAUTH? I tried doing something similar. I tried to do something similar and I set the constant in the Build tab of the project properties but the constant is visible only in cs files or when using the RazorGenerator tool. I suppose it is because Razor compiles only at runtime and it has no way of knowing what was defined at build time? How do YOU use it? Thanks! (Note: I'm in .NET Framework 4.8) – bkqc Aug 28 '23 at 15:07
  • NOEXTAUTH is just a solution configuration we added alongside Debug and Release. This example could equally just be #if DEBUG for example. – Mr Moose Sep 01 '23 at 03:02