MVC 3 Razor 视图:从布尔模型值生成 JavaScript

Posted

技术标签:

【中文标题】MVC 3 Razor 视图:从布尔模型值生成 JavaScript【英文标题】:MVC 3 Razor View: Generating JavaScript from a boolean model value 【发布时间】:2011-12-19 11:18:15 【问题描述】:

我正在使用 ASP.Net MVC 3 Razor 视图引擎。

我需要根据我的视图模型中的值在我的视图中生成一些 javascript 代码。我需要使用的值是一个布尔值,在这个例子中我们称之为IsSet

所以我想做的是基于这个值创建一个 JavaScript 布尔值,以便稍后在脚本中使用。

请记住,对于以下所有示例,我的视图顶部都有这段代码...

@ string IsSet = Model.IsSet  ? "true" : "false"; 

注意:以下所有示例均为 JavaScript。

第一次尝试...

var IsSet = @(IsSet);

...这确实有效,问题是它破坏了 VS 2010 中的自动格式化(CTRL + E,D),因为 JavaScript 格式不正确 - 正如您所料,这是不可接受。

第二次尝试...

var IsSet = "@(IsSet)";

...我知道,JavaScript 很聪明,它会在需要时自动解析我的字符串。哎呀,忘了它是一个字符串类型,除了空之外的任何东西都会评估为真。

第三次尝试...

var IsSet = Boolean("@(IsSet)");

....这肯定行得通...不,再次将非空字符串转换为真(错误的解析器!)

第四次尝试...

var IsSet = "@(IsSet)" === "true";

终于有一个可行的方法,但对我来说看起来不太好。

如果需要,我会使用它,但最终我的问题是:有没有更好的方法来处理这种情况?也许,我第一次尝试时出现的不良行为只是 Microsoft 可能忽略的事情?

如果有人对我有一个漂亮而整洁的第五次尝试,那就太好了。

对我来说重要的是 VS 2010 中的自动格式化不会中断

谢谢

【问题讨论】:

我必须同意你的第一次尝试——这对我来说看起来是最自然的,因为你没有先进行字符串化,然后再投射一些本来就已经是布尔值的东西!我在我的 Razor / JS 代码中大量使用了这种技术,它似乎工作正常,而且我没有看到自动格式化有任何问题,但我确实使用了 ReSharper,所以也许它会自动修复它! 我使用 ReSharper,但仍然遇到自动格式化问题,所以我不确定这就是您没有遇到格式化问题的原因。当 Pascal 大小写的 Razor 变量出现在格式化程序将强制小写命名的位置时,会出现自动格式化和大写问题,例如 html 标记名称或 JS 代码(主要是 camelCase;特别是,格式化程序在自动缩进时启动发生了......所以克里斯,我有一种预感,你可能有不同的情况? 【参考方案1】:

我只是在同一个问题上挣扎了大约一个小时。我的最终解决方案相当于以下内容。

var IsSet = @(Model.IsSet.ToString().ToLower()); // Inside JavaScript block

这不需要额外的代码。

【讨论】:

这将以与第一次尝试相同的方式中断。 Intellisense 将无法识别为变量初始化编写的内容,并在分号处显示红色波浪线。 完美的 MVC 4.tks【参考方案2】:

到目前为止显示的版本(包括问题和答案)都不是我会使用的。以下是我的做法:

@model MyViewModel
<script type="text/javascript">
    var isSet = @Html.Raw(Json.Encode(Model.IsSet));

    // TODO: use the isSet javascript variable here as a standard boolean value
</script>

或者如果您需要使用 javascript 操作视图模型的其他属性,您可以对整个模型进行 JSON 编码:

@model MyViewModel
<script type="text/javascript">
    var model = @Html.Raw(Json.Encode(Model));

    if (model.IsSet) 
        alert(model.FooBar);
    
</script>

【讨论】:

不错的选择,但这仍然会破坏 JavaScript 的自动格式化。另外,就目前而言,我收到一个错误“条件编译已关闭”...添加的括号解决了这部分问题...@(Html.Raw(Json.Encode(Model.IsSet))); @musefan,Razor 中的 Intellisense,尤其是与 javascript 混合时非常糟糕。这是我很久以前就不再担心的事情了。希望微软会在未来的某个版本中修复它。它发出一些不应该发出的警告。就我个人而言,我专注于编写不易受到 XSS 注入攻击的正确代码,......而且我知道它会在运行时正常工作,因为它可以正确编码所有内容。 VS 在一些完全有效的代码上给我警告的事实应该归咎于 VS 的设计者,而不是你作为这段代码的作者。 这是一个不错的选择。虽然它打破了自动格式化,这只会在一开始就出现问题,没有其他服务器端代码混合到 JavaScript 中。【参考方案3】:

版本 1 是唯一一个我会投票支持的版本,即使它们都有效,因为它是最易读的。不幸的是,我家里没有 VS,所以我无法尝试查看自动格式化问题是什么,但如果可能的话,我想忽略这个问题并继续使用该版本,因为有代码实际上没有任何问题 - 只是 VS 被混淆了。 (你是说 VS 试图将整个事情解释为 JS 并因此发现它无效?)

但如果你想要一些其他的选择:

第五次尝试...

@ string IsSet = Model.IsSet  ? "true" : ""; 

var isSet = !!"@(IsSet)";
// OR
var isSet = Boolean("@(IsSet)");

使用旧的双非运算符技巧将字符串值强制转换为布尔值 - 正如您已经指出的那样,“true”和“false”都会变为 true,但是如果您使用“true”和“ " (空字符串) - 所以你可以根据你的“第三次尝试”使用Boolean()

第六次尝试...

@ string IsSet = Model.IsSet  ? "true" : "false"; 

// helper function at the top of your page:
function bool(strVal) 
   return strVal === "true";


// variable declaration
var isSet = bool("@(IsSet)");

好的,所以你最终会在页面顶部得到一个相当无意义的函数,但它使实际的变量声明保持相当整洁,如果调试客户端,你会看到 bool("false")bool("true")

第七次尝试……

我不喜欢提前创建服务器端string IsSet = Model.IsSet ? "true" : "false"; 的额外步骤。我不知道 Razor 语法,但你能说一下:

var isSet = !!"@(Model.IsSet ? "true" : "")";
// OR, better:
var isSet = !!"@(rzrBool(Model.IsSet))";
// where rzrBool() is a server-side helper function (that you would create)
// which returns "true" or ""

我希望我所有的“尝试”都能奏效,但我再次认为你的“第一次尝试”是最好的选择。

【讨论】:

顺便问一下,你说@(IsSet)的任何地方都需要括号吗?或者你可以直接说@IsSet吗?如果后者没问题,那将使每个变化都更整洁。 首先,自动格式化的问题是当你的 JavaScript 无效时它什么也做不了。如果您错过了函数调用等中的右括号,同样适用。其次,您的答案看起来都可行,除了您的第七个可能需要使用 ' 来包装整个字符串以避免包含引号的问题,而且这个选项看起来也很讨厌.我同意第一个是最好的,但是自动格式化太重要了,不能放弃。我可以使用 bool 函数,因为我有其他视图可以做类似的事情。 我怀疑我的“5b”是您的最佳选择。不需要任何附加功能(客户端或服务器端),就像您修改服务器端代码以返回“true”或空字符串而不是“true”或“false”后的第三次尝试。 (关于我的 7a,是的,你需要在外部使用单引号来让 VS 开心,尽管它应该按原样运行。)【参考方案4】:

怎么样:

@Ajax.ToJson(Model.IsSet)

【讨论】:

什么是@Ajax.ToJson()?它没有出现在我的智能感知或 Google 中【参考方案5】:
var isSet = /true/i.test('@Model.IsSet');
单行 处理 .Net 和 JavaScript 之间的大小写差异 适用于自动格式化(Visual Studio 和带有 Resharper 的 Visual Studio) 如果您熟悉 JavaScript 正则表达式,则相当地道 对逻辑错误具有相当的弹性;它应该按预期执行或引发 JavaScript 错误(或可能是 Razor 编译错误)。

【讨论】:

【参考方案6】:

怎么样:

@Model.IsSet.ToString().ToLower()

【讨论】:

不好。我假设您的意思是直接在 JavaScript 块中使用它?如果你的意思是替换我的 C# razor 代码的第一行,那么它也不会有什么不同。 它为我打印出 False.... 也许如果您将 .ToLower() 添加为 false,则 var something = @Model.IsSet.ToString().ToLower(); 是的,它会工作。但就像我的第一次尝试一样,它打破了 VS 2010 中的自动格式化 或者如果您在模型中将 IsSet 设为字符串,并在为其赋值时对其进行格式化。 我将它作为我的代码顶部的字符串。 Teh 自动格式化不喜欢 JavaScript 块中的随机 @ 字符。这就是问题【参考方案7】:
var isSet= @((bool)Model.IsSet?"true":"false");

【讨论】:

这是一个糟糕的答案。首先,将Model.IsSet 转换为 bool 是没有意义的,因为它已经是 bool 了。其次,如果您打算在 JavaScript 中执行此操作,您仍然遇到与我第一次尝试相同的问题(自动格式化中断)【参考方案8】:

这是我在 javascript 块中使用的内容:

var someValue;
@ var someValue= "someValue= " + Model.SomeValue+ ";"; 
@someValue

【讨论】:

【参考方案9】:

我知道这是一个老问题,但没有一个答案特别优雅。

在这些情况下,最简单的解决方案是将+0 附加到您的条件。这会隐式地将 bool 转换为 int,但由于结果是 01,它会立即被 if 语句再次转换回来。示例:

// The space is optional
if (@IsSet +0) 
    // Do stuff

将布尔值分配给变量可以实现如下:

// Note the double (not triple) equals, which performs type conversion
var isSet = @IsSet+0 == true;

代码有效,没有红色波浪线,Visual Studio 格式化程序很满意。

【讨论】:

以上是关于MVC 3 Razor 视图:从布尔模型值生成 JavaScript的主要内容,如果未能解决你的问题,请参考以下文章

使用 MVC Razor 语法检查视图模型属性在 Javascript 中是不是具有值

MVC3 Razor - 模型和视图

.net MVC,Razor语法详细介绍

ASP.NEt MVC 使用 Web API 返回 Razor 视图

使用单一视图模型在 MVC Razor 视图上发布多个表单

MVC 3 Razor Form Post w/ 多个强类型的部分视图不绑定