如何使用 MVC4 和 Razor 设置 javascript 变量

Posted

技术标签:

【中文标题】如何使用 MVC4 和 Razor 设置 javascript 变量【英文标题】:How to set javascript variables using MVC4 with Razor 【发布时间】:2013-01-29 18:22:37 【问题描述】:

有人可以格式化下面的代码,以便我可以使用 razor 使用 c# 代码设置 srcript 变量吗?

下面的方法不起作用,我知道这样做很容易让别人帮忙。

@int proID = 123; int nonProID = 456;

<script type="text/javascript">
    @

     <text>  

    var nonID =@nonProID;
    var proID= @proID;
    window.nonID = @nonProID;
    window.proID=@proID;

    </text>

</script>

我遇到了设计时错误

【问题讨论】:

“不起作用”。怎么不行? 这可能是新的,但var nonID =@(nonProID); 为我工作。 【参考方案1】:

您应该查看剃刀页面生成的输出。实际上,您需要知道server-sideclient-side 执行了什么。试试这个:

@
    int proID = 123; 
    int nonProID = 456;


<script>

    var nonID = @nonProID;
    var proID = @proID;
    window.nonID = @nonProID;
    window.proID = @proID;

</script>

输出应该是这样的:

根据您使用的 Visual Studio 版本,它会在设计时为带有 razor 的视图指出一些亮点。

【讨论】:

在设计时,Visual Studio 说这是 sintax 错误,但它呈现正确的输出。看看我的编辑。 @FelipeOriani 将其包裹在&lt;text/&gt; 标签中:例如:var nonID = @nonProID&lt;text&gt;;&lt;/text&gt; 是的,VS 会在脚本标签内给你误导性的错误,但代码可以正常工作。 你说得对,VS 会产生误导性错误。谢谢【参考方案2】:

由于在处理视图时可能会出现 razor 语法错误,因此我完全明白为什么要避免它们。这里有几个其他选项。

<script type="text/javascript">
    // @Model.Count is an int
    var count = '@Model.Count';
    var countInt = parseInt('@Model.ActiveLocsCount');
</script>

引号充当分隔符,因此剃刀解析器很高兴。但当然,您的 C# int 在第一条语句中变成了 JS 字符串。对于纯粹主义者来说,第二种选择可能更好。

如果有人有更好的方法来做到这一点而不会出现剃刀语法错误,特别是保持 var 的类型,我很乐意看到它!

【讨论】:

对我来说这是唯一的解决方案,完美运行:D【参考方案3】:

这就是我解决问题的方法:

@int proID = 123; int nonProID = 456;

<script type="text/javascript">
var nonID = Number(@nonProID);
var proID = Number(@proID);
</script>

它是自记录的,不涉及到文本的转换。


注意:小心使用 Number() 函数,不要创建 new Number() 对象 - 因为完全等于运算符的行为可能不明显:

var y = new Number(123); // Note incorrect usage of "new"
var x = new Number(123);
alert(y === 123); // displays false
alert(x == y); // displays false

【讨论】:

@hectorct 非常正确我想我必须测试过var y = new Number(123),因为这会产生错误。已更新答案。感谢您的提醒!【参考方案4】:

我已经看到了几种解决该错误的方法,并且我运行了一些计时测试以了解哪些方法可以提高速度 (http://jsfiddle.net/5dwwy/)

方法:

    直接分配

    在这种方法中,剃刀语法直接分配给变量。这就是引发错误的原因。作为基线,JavaScript 速度测试只是将数字直接分配给变量。

    通过 `Number` 构造函数

    在这种方法中,我们将 razor 语法包装在对 `Number` 构造函数的调用中,就像在 `Number(@ViewBag.Value)` 中一样。

    解析整数

    在这种方法中,剃刀语法放在引号内并传递给 `parseInt` 函数。

    值返回函数

    在这种方法中,创建了一个函数,它简单地将剃刀语法作为参数并返回它。

    类型检查功能

    在这种方法中,函数会执行一些基本的类型检查(基本上是查找 null),如果不为 null,则返回该值。

程序:

使用上述每种方法,for-loop 重复每个函数调用 10M 次,得到整个循环的总时间。然后,该 for 循环重复 30 次以获得每 10M 动作的平均时间。然后将这些时间相互比较,以确定哪些操作比其他操作更快。

请注意,由于是 JavaScript 运行,其他人收到的实际数字会有所不同,但重要性不在于实际数字,而是数字与其他数字的比较。

结果:

使用直接分配方法,处理 1000 万个分配的平均时间为 98.033 毫秒。使用 Number 构造函数每 10M 产生 1554.93ms。同样,parseInt 方法花费了 1404.27 毫秒。两个函数调用对于简单函数耗时 97.5ms,对于更复杂函数耗时 101.4ms。

结论:

要理解的最简洁的代码是直接赋值。但是,由于 Visual Studio 中的错误,这会报告错误,并可能导致 Intellisense 出现问题并给人一种模糊的错误感觉。

最快的代码是简单的函数调用,但只是微不足道。由于我没有做进一步的分析,我不知道这种差异是否具有统计学意义。类型检查功能也非常快,只比直接赋值稍慢,并且包括变量可能为空的可能性。不过,这并不实用,因为如果参数未定义(剃刀语法中为 null),即使是基本函数也会返回 undefined。

将 razor 值解析为 int 并通过构造函数运行它非常慢,比直接赋值慢 15 倍。很可能Number 构造函数实际上在内部调用parseInt,这可以解释为什么它比简单的parseInt 需要更长的时间。但是,它们确实具有更有意义的优点,不需要执行外部定义的(即文件或应用程序中的其他位置)函数,Number 构造函数实际上最小化了整数到字符串的可见转换。

归根结底,这些数字是经过 10M 次迭代生成的。单品上,速度小得不可估量。对于大多数人来说,简单地通过Number 构造函数运行它可能是最易读的代码,尽管它是最慢的。

【讨论】:

这个答案太棒了。在研究性能方面做得很好。【参考方案5】:
@
int proID = 123; 
int nonProID = 456;


<script>

var nonID = '@nonProID';
var proID = '@proID';
window.nonID = '@nonProID';
window.proID = '@proID';

</script>

【讨论】:

【参考方案6】:

一种简单的方法是:

<input type="hidden" id="SaleDateValue" value="@ViewBag.SaleDate" />
<input type="hidden" id="VoidItem" value="@Model.SecurityControl["VoidItem"].ToString()" />

然后在javascript中获取值:

var SaleDate = document.getElementById('SaleDateValue').value;
var Item = document.getElementById('VoidItem').value;

【讨论】:

这种方式适用于字符串,其他建议似乎不适用于它们。 任何类型的数据都可以通过这种方式轻松处理。它不仅仅与字符串数据类型有关。您可以再次解析JavaScript 中的数据类型。 处理 js 模块和 .net 变量的好方法。 是的,我觉得它最简单。 ;-)【参考方案7】:

我找到了一个非常干净的解决方案,它允许单独的逻辑和 GUI:

在你的 razor .cshtml 页面中试试这个:

<body id="myId" data-my-variable="myValue">

...your page code here

</body>

在您的 .js 文件或 .ts(如果您使用 typeScript)中从您的视图中读取存储的值,放置一些类似这样的内容(需要 jquery 库):

$("#myId").data("my-variable")

【讨论】:

其中 myValue 可以替换为 c# 变量:@myCSharpVariable【参考方案8】:

与其说是一个警示故事,不如说是一个答案:这也困扰着我——我认为我有一个解决方案,方法是在前面加上一个零并使用 @(...) 语法。即您的代码将是:

var nonID = 0@(nonProID);
var proID = 0@(proID);

得到如下输出:

var nonId = 0123;

我没有意识到这就是 JavaScript(版本 3)表示八进制/base-8 数字的方式,并且实际上正在改变值。此外,如果您使用 "use strict"; 命令,那么它将完全破坏您的代码,因为八进制数已被删除。

我仍在寻找合适的解决方案。

【讨论】:

不太了解问题,但尝试在前面加上 +【参考方案9】:

如果你这样做,它会起作用:

var proID = @proID + 0;

生成的代码类似于:

var proID = 4 + 0;

确实有点奇怪,但至少没有更多虚假的语法错误。 遗憾的是,在 VS2013 中仍会报告错误,因此尚未正确解决(目前)。

【讨论】:

【参考方案10】:

我一直在研究这种方法:

function getServerObject(serverObject) 
  if (typeof serverObject === "undefined") 
    return null;
  
  return serverObject;


var itCameFromDotNet = getServerObject(@dotNetObject);

对我来说,这似乎让 JS 方面更安全......最坏的情况是你最终会得到一个空变量。

【讨论】:

【参考方案11】:

这应该涵盖所有主要类型:

public class ViewBagUtils

    public static string ToJavascriptValue(dynamic val)
    
        if (val == null) return "null";
        if (val is string) return val;
        if (val is bool) return val.ToString().ToLower();
        if (val is DateTime) return val.ToString();
        if (double.TryParse(val.ToString(), out double dval)) return dval.ToString();

        throw new ArgumentException("Could not convert value.");
    

并且在&lt;script&gt; 标记内的.cshtml 文件中:

@using Namespace_Of_ViewBagUtils
const someValue = @ViewBagUtils.ToJavascriptValue(ViewBag.SomeValue);

请注意,对于字符串值,您必须在单(或双)引号内使用 @ViewBagUtils 表达式,如下所示:

const someValue = "@ViewBagUtils.ToJavascriptValue(ViewBag.SomeValue)";

【讨论】:

【参考方案12】:

我使用一个非常简单的function 来解决与Razor 代码混合的JavaScript 代码正文中的语法错误;)

function n(num)return num;

var nonID = n(@nonProID);
var proID= n(@proID);

【讨论】:

【参考方案13】:

这会直接从 web.config 定义的 appSetting 为我设置一个 JavaScript 变量。

var pv = '@System.Web.Configuration.WebConfigurationManager.AppSettings["pv"]';

【讨论】:

【参考方案14】:

var jsVar = JSON.parse(@Html.Raw(Json.Serialize(razorObject)));

您可以将任何 razor 对象解析为 JavaScript 对象。

它很长但很普遍

【讨论】:

以上是关于如何使用 MVC4 和 Razor 设置 javascript 变量的主要内容,如果未能解决你的问题,请参考以下文章

[转载].NET MVC4 Razor 视图预编译

在 MVC4 razor 中使用“远程”验证处理多个提交按钮

C# MVC4 Razor 部分视图 - 切换视图时刷新整页?

ASP.net MVC4 和 Razor:得到 403 错误

为啥在 MVC4 Razor 视图中找不到扩展方法?

ASP.NET MVC4 Razor