Preprocessor Directives in Razor

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

In your model:

bool isRelease = false;

<% #if (RELEASE) %>
isRelease = true;
<% #endif %>

In your view:

<% if (Model.isRelease) { %>
<div class="releaseBanner">Banner text here</div>
<% } else { %>
<div class="debugBanner">Banner text here</div>
<% } %>

Pre-processing equivalent for views in RAZOR/MVC 3

That's too messy IMO. Views should be dumb, and focused on rendering HTML, not making build-based decisions.

Set properties in your view model if debug is configured, and render them out in the View.

If the properties are null (e.g non-debug), nothing will get rendered.

Preprocessor directives per launch settings in .Net Core

The problem with your question is that a preprocessor directive is used and evaluated at compile time, not run time. So if you want a "easy" switch, you have to define it in your csproj as a build configuration. You have to add a build configuration to your csproj file:

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='WebListener|AnyCPU'">
<DefineConstants>DEBUG</DefineConstants>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='IISExpress|AnyCPU'">
<DefineConstants>DEBUG</DefineConstants>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
</PropertyGroup>

And you have to add the information, which build configurations are awailable:

<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Configurations>Debug;Release;WebListener;IISExpress</Configurations>
</PropertyGroup>

so you can use your code as example

#if WEBLISTENER
.UseWebListener(options =>
{
options.ListenerSettings.Authentication.Schemes = AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM;
options.ListenerSettings.Authentication.AllowAnonymous = false;
})
#endif

#if IISEXPRESS
/* ... */
#endif

BUT: With this solution you have to change both, the launch settings AND the build settings, to switch between your configurations:

Build + Launch Configurations

For more information you can look into these ressources:

  • Creating custom build configurations for the .NET Core project format
  • How to use custom preprocessor directives in .Net Core

How to use Preprocessor directives in MVC aspx pages

You can use the following:

if (!HttpContext.Current.IsDebuggingEnabled)
Script = OptimizeScript(Script);

Further.....there are a couple of comments than discuss the topic further.

From Wilco Bauwer he comments that this property encapsulates the web.config setting and doesn't take the page level debugging into account and if you wanted to....

bool isDebuggingEnabled = Assembly.GetExecutingAssembly().IsDefined(typeof(DebuggableAttribute));

....this is the kiddy to achieve it!!

and Peter Bromberg (C# MVP) offers up another solution using the Global.asax.cs file and a static global application flag being set in the Application_Start event.

public static bool IsDebugMode = false;
protected void Application_Start(object sender, EventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached) IsDebugMode = true;

Taken from Steves blog

What does @using and @namespace directives do in a Razor _ViewImports.cshtml file?

Whatever namespaces you mention using @namespace in the ViewImports.cshtml file will be available to your views (.cshtml files) automatically without the use of @using. In other words, they will be available implicitly. If not mentioned in the ViewImports.cshtml file, you will still need to use @using.

From documentation

The @namespace directive was designed so the C# classes added to a project and pages-generated code just work without having to add an @using directive for the code behind file.

In other words, if you add the @namespace to the _ViewImports.cshtml file, then the other files will not need to use @using in each one of them.

What is _ViewImports.cshtml`?

From the docs:

_ViewImports.cshtml serves one major purpose: to provide namespaces which can be used by all other views. In previous MVC projects, this functionality was provided by the web.config file in the Views folder; since the web.config no longer exists, global namespaces are now provided by this file.

More Explanation

In MVC5 and earlier versions, if you check the Views/web.config file, you will notice xml and amongst it you will notice this or possible more <add elements:

<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="Mvc" />
</namespaces>

That is basically instructing the Razor engine, that all the .cshtml files within this specific Views folder will need those namespaces and thus the .cshtml files can use those namespaces without @using for these namespaces. In MVC6, the Views/web.config no longer exists and it is replaced by ViewImports.cshtml file which serves the same purpose.

Ok great, so what is @using for then?

You will still need @using in the .cshtml files for whatever namespaces are not imported using @namespace in the ViewImports.cshtml file. For example, if you have a view named Edit.cshtml, then you may have this:

@using NamespaceA;

Which means this namespace is imported explicitly to be available for Edit.cshmtl file. A few other namespaces, which are mentioned in ViewImport.cshtml file will be automatically available to Edit.cshtml file.

is there a tool to propagate preprocessor directives?

No, basically. However, what you can do is split your code into two files and make use of partial class such that all your bar code is in one isolated file:

partial class foo
{
partial void OnBar(bool value);
public void Do()
{
OnBar(false);
}
}

and

#if bar
partial class foo
{
private bool bar;
partial void OnBar(bool value)
{
bar = value;
}
}
#endif

Now the main file knows nothing about bar. If the bar compilation symbol isn't defined, the bar field doesn't exist, and nor does the OnBar method - the method and it's invocations simply evaporate.

This can be useful in many scenarios, including additional levels of debugging code, or targeting multiple platforms / frameworks / operating systems (with specific files for different targets) - without your code being filled with #if.

How to follow preprocessor directives throughout a compilation

I think you're on the right track with the /P option, but the doc states that the output will go to files with a .i extension (so probably not to your Output window).

Further, you may be able to find some help on any linker errors by generating a map file; see /MAP (Generate Mapfile).



Related Topics



Leave a reply



Submit