Using conditional compilation symbols in MVC views
Asked Answered
D

4

9

In "Properties" of my project I have the following:

enter image description here

I want to check if TEST symbol exists, and only then, do some things. So I did what you see in the picture below and in the class it works. However this does not work in the views.

enter image description here

The text in this block is gray even if TEST is defined!

How can I cause it work if TEST is defined?

Daytime answered 30/11, 2011 at 11:8 Comment(0)
M
11

The problem is related to the fact that views are only compiled when you run your application so the TEST symbol that you defined is no longer applied by the compiler because it has no knowledge of it.

Assuming that you are using C# you need to configure the compiler to use the TEST symbol when building the views and for this you need to override its configuration in Web.config using the following:

<system.codedom>
  <compilers>
    <compiler
      language="c#;cs;csharp"
      extension=".cs"
      type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
      compilerOptions="/define:TEST"
      warningLevel="1" />
  </compilers>
</system.codedom>

The important part is that you define compilerOptions="/define:TEST". The rest of the configuration you need to adapt to your specific needs, for example switch between .NET 2.0 or .NET 4.0.

If you apply this directly in the Web.config it will work but will define TEST every time. So what you should really do is use Web.config transformations so that the symbol is only applied for the correct build configurations.

Mesoglea answered 30/11, 2011 at 11:52 Comment(4)
Yes, now the text isn't "gray" - but it works either if I delete the "TEST" or not...Daytime
You need to synchronize both definitions of TEST. If you remove it from the project properties you also need to remove it from configuration.Dumortierite
It's like- TEST in web.config is for views and TEST in the project properties is for the rest... right?Daytime
I'm pretty late to this question, but posted an alternative that does not require defining the compiler parameters including compiler version in web.config.Internationalism
I
18

Rather than specify the compiler flag in web.config as per the accepted answer (which also requires specifying the compiler version in web.config, which is a non-standard location) I went with the following:

Add a method to a base class shared by my models

public bool IsDebugBuild 
{ 
    get
    {
        #if DEBUG
        return true;
        #else
        return false;
        #endif
    }
}

Use that method in my views

if (mm.IsDebugBuild) {
    <div class="debug">
    // Do Stuff
    </div>
}
Internationalism answered 3/5, 2012 at 19:24 Comment(4)
Isn't this effectively the same thing that Dangerous suggested?Derbent
No, the difference being that I use a flag that is automatically set at build time (see the first sentence of my answer).Internationalism
This method also works more consistently (i.e. more as expected) when running and testing Debug vs. Release builds locally, without publishing them.Associationism
Do you mean that the only difference is that you have the value directly returned from the property instead of setting it in the constructor? If that's the case, it is only a different implementation of the same solution...Paramatta
M
11

The problem is related to the fact that views are only compiled when you run your application so the TEST symbol that you defined is no longer applied by the compiler because it has no knowledge of it.

Assuming that you are using C# you need to configure the compiler to use the TEST symbol when building the views and for this you need to override its configuration in Web.config using the following:

<system.codedom>
  <compilers>
    <compiler
      language="c#;cs;csharp"
      extension=".cs"
      type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
      compilerOptions="/define:TEST"
      warningLevel="1" />
  </compilers>
</system.codedom>

The important part is that you define compilerOptions="/define:TEST". The rest of the configuration you need to adapt to your specific needs, for example switch between .NET 2.0 or .NET 4.0.

If you apply this directly in the Web.config it will work but will define TEST every time. So what you should really do is use Web.config transformations so that the symbol is only applied for the correct build configurations.

Mesoglea answered 30/11, 2011 at 11:52 Comment(4)
Yes, now the text isn't "gray" - but it works either if I delete the "TEST" or not...Daytime
You need to synchronize both definitions of TEST. If you remove it from the project properties you also need to remove it from configuration.Dumortierite
It's like- TEST in web.config is for views and TEST in the project properties is for the rest... right?Daytime
I'm pretty late to this question, but posted an alternative that does not require defining the compiler parameters including compiler version in web.config.Internationalism
R
2

The symbol you set is only used during compilation. It does not exist otherwise. So, your web project's DLL does not have that symbol at all. Therefore, when the View is compiled. the symbol isn't there, and it won't work as you are expecting.

Rori answered 30/11, 2011 at 11:13 Comment(0)
D
1

I don't think its possible to use conditional symbols in a view as Andrew Barber has already said.

But you could use conditional symbols in the model:

public class ViewModel
{
//...whatever else you need to define

    private bool test;

    public bool Test
    {
        get
        {
            return test;
        }
    }

    public ViewModel()
    {
        #if (TEST)
            test = true;
        #endif
    }
}

And then check the value in the view:

@{
    if (Model.Test)
    {
        <p>debug statements here</p>
    }
}
Depurate answered 30/11, 2011 at 11:46 Comment(2)
Do I have to do it just in ViewModel ?Daytime
@ParPar: You would have to do the check in the view model (where compilation symbols can be used) which would then set a view model flag. In the answer above I have set this flag in the view model constructor. That flag can then be tested for after it has been passed to the model.Depurate

© 2022 - 2024 — McMap. All rights reserved.