Razor 中的预处理器指令

Posted

技术标签:

【中文标题】Razor 中的预处理器指令【英文标题】:Preprocessor directives in Razor 【发布时间】:2011-06-09 10:21:40 【问题描述】:

我今天正在写我的第一个 Razor 页面,但不知道如何进入

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

如何在 Razor 中做到这一点?

【问题讨论】:

***.com/questions/378982/…的可能重复 我的意思是你希望#if debug 使用剃须刀,但它总是是真的。所以你的问题的答案是这样做是没有意义的,因为 Razor 总是在调试模式下编译。 【参考方案1】:

我需要在 <script> 标记中也可以使用的类似内容,并且发现以下内容适用于 DOM 中的条件标记或条件脚本。

@
#if NOEXTAUTH

    @:<!-- A single line block of code -->

    <text>
        <!--
        A multi-line block    
        -->
    </text>

#endif

【讨论】:

所有其他答案完全没有抓住重点。在所有其他答案中,仍然有一个“如果”,它将在发布中并被执行。这是最好的答案。【参考方案2】:

这适用于 .NET Core 3.0 白标项目:

@
#if CORPA

    <button type="button" class="btn btn-warning">A Button</button>
@
#else

    <p>Nothing to see here</p>
@
#endif

【讨论】:

【参考方案3】:

在 .NET Core 中,您可以使用 environment tag helper 而不是检查预处理器变量:

<environment include="Development">
    <!--Debug code here-->
</environment>

【讨论】:

【参考方案4】:

这是built in to HttpContext

@if (HttpContext.Current.IsDebuggingEnabled)

    // Means that debug="true" in Web.config

IMO,这比视图的条件编译更有意义,并且在某些测试场景中派上用场。 (见下文Tony Wall's comment。)


旁注:NullReferenceException 代表HttpContext.Current

Alex Angas mentioned 表示他们通过此解决方案获得了NullReferenceException,并且一些人表示这可能不是一个孤立的事件。

我的最佳猜测:HttpContext.Current 存储在CallContext 中,这意味着它只能由处理传入 HTTP 请求的线程访问。如果您的视图在不同的线程上呈现(可能是预编译视图的一些解决方案?)您将获得nullHttpContext.Current 值。

如果您收到此错误,请在 cmets 中告诉我,并说明您是否使用预编译视图或任何可能导致您的视图在另一个线程上部分呈现/执行的特殊设置!

【讨论】:

优势在于您可以在集成测试环境中打开它来诊断部署问题,这些问题通常在安装在非开发人员 PC 上时才会出现。 我得到一个空引用异常,可能是因为在发布模式下,调试属性已从 web.config 中完全删除。 @AlexAngas 无法复制。 :( 我在 .NET 4.5.1(ASP.NET MVC 5,System.Web 版本 4.0.0.0)中创建了一个项目,即使删除了 debug 属性(或者实际上是整个 compilation 元素)我也删除了不要例外。我的下一个最佳假设是,这是在System.Web 程序集的更高版本中修复的错误,或者我不知道您的具体情况有什么不同。你能创建一个最小的测试项目并将其上传到某个地方? @JordanGray 感谢您的关注——我也刚刚尝试了一个新项目,但也无法复制!您的解决方案正在运行。不幸的是,目前没有时间进一步研究,但如果我遇到原因,我会更新这篇文章。 该死的聪明伙伴;这应该是 OP 的答案。【参考方案5】:

我的解决方案非常愚蠢,但它确实有效。 在静态文件的某处定义一个全局常量:

public static class AppConstants

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

然后在 html 中将它与 Razor 一起使用:

@if (AppConstants.IS_DEBUG)

    <h3>Debug mode</h3>

else

    <h3>Release mode</h3>

【讨论】:

恕我直言,这没那么愚蠢。在调试中我想使用 es6-javascript(所以我在开发时看到 es6 错误),在发布中我想使用自动转换的非 es6-javascript(因为 IE11 不知道 es6)。这对我来说是一个很好的解决方案。 不错 - 简单直接,明确 爱它...我有一个用于 appSetting 的全局静态类...这个插件很好。 我遇到了这个解决方案的问题,它在调试版本中工作,但在发布版本中得到“AppConstants 在此上下文中不存在”。有什么想法吗? 我的猜测是您删除了 Razor 页面中的引用“@using ...”(相对于 AppConstants 命名空间)。或者您可以将整个 AppConstants 声明放在“#if DEBUG”下。【参考方案6】:

对我来说,下面的代码运行良好。

当应用程序调试时,我的按钮出现,释放时,它们不会出现。

@if (this.Context.IsDebuggingEnabled)

    <button type="button" class="btn btn-warning">Fill file</button>
    <button type="button" class="btn btn-info">Export file</button>
 

【讨论】:

【参考方案7】:

我刚刚创建了一个扩展方法:

public static bool IsDebug(this HtmlHelper htmlHelper)

#if DEBUG
      return true;
#else
      return false;
#endif

然后像这样在我的视图中使用它:

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

由于帮助程序是使用 DEBUG/RELEASE 符号编译的,所以它可以工作。

【讨论】:

当然这个扩展方法必须进入MVC项目,而不是进入一个单独的库,可能用不同的选项编译... 这对我来说根本不起作用 - 无论编译模式如何,它都会产生“True”。 Jordan Gray 的回答非常有效。 如果是 DEBUG 模式,预处理器基本上会读取public static bool IsDebug(...) return true; ,反之亦然非 DEBUG 模式。 这对我有用,只需对 .Net Core 稍作调整:必须将 HtmlHelper 更改为 IHtmlHelper。希望对某人有所帮助。【参考方案8】:

我知道这不是问题的直接答案,但我很确定调试配置是您实际在本地执行的事实的必然结果,您始终可以使用 Request.IsLocal 属性作为调试之类的测试。因此:

@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">

【讨论】:

不一定。您可以在测试/开发服务器上以调试模式运行,例如,在暂存/生产上以发布模式编译之前。 在这种情况下,呈现链接标签的 html 辅助扩展方法将有所帮助。在扩展方法中,您可以使用#if DEBUG 或配置变量来决定环境。【参考方案9】:

默认情况下,MVC 视图未编译,因此#IF DEBUG 无法在视图中工作。如果你想编译视图以访问 IF DEBUG 配置,你需要:

    在 Visual Studio 中右键单击您的项目 卸载项目 编辑项目

将以下属性从 false 更改为 true

<MvcBuildViews>true</MvcBuildViews>

重新加载您的项目,然后将编译视图。

唯一的其他解决方法是在您的代码中添加一个函数

public static Boolean DEBUG(this System.Web.Mvc.WebViewPage page)

   var value = false;
   #if(DEBUG)
       value=true;
   #endif
   return value;

然后从视图中调用它:

if(DEBUG())

  //debug code here

else

  //release code here

【讨论】:

【参考方案10】:

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

其实那个答案是正确的。无论您是否处于调试模式,您都必须通过模型传递。 (或 ViewBag),因为所有视图都是在调试模式下编译的。

【讨论】:

请注意,由于 Razor 视图始终在调试模式下编译,因此以这种方式设置预处理器指令实际上不会产生任何效果。你将永远执行// your debug stuff 嘿,是的,我写的时候才意识到。

以上是关于Razor 中的预处理器指令的主要内容,如果未能解决你的问题,请参考以下文章

Go中的预处理器指令就像C中的一样[重复]

为啥 C 预处理器不忽略它跳过的块中的无效指令?

C 中的预处理器指令:使用 __LINE__ 的宏

c++ 中的预处理器指令:以下代码的输出是啥?

C#预处理器指令

Quantlib 预处理器指令