ASP.NET Core Razor 页面:将值从 Foreach 传递给 JavaScript 函数

时间:2021-07-19 17:30:56

标签: asp.net-core razor

我正在尝试将值从 C# 对象传递给 JavaScript 函数。 但我收到一个错误:

@foreach (var Item in Model.Student)  
{
    <input id="btnAdd" type="button" value="Add" onclick="AddTextBox(JSON.parse(@Html.Raw(Item)))"/>
}

Model.Student 属性返回一个 Student 对象,其定义如下:

public class Student 
{ 
    public int Id { get; set; } 
    public string name { get; set; } 
} 

1 个答案:

答案 0 :(得分:3)

您需要做三件事来解决这个问题:

  1. 使用 Student 将您的 Item 对象 (Json.Serialize()) 序列化为 JSON,
  2. 使用 HttpUtility.JavaScriptStringEncode() 将您的 JSON 编码为 JavaScript 字符串,并且
  3. 将您的 JSON 包裹在撇号中,以便 JSON.parse() 正确地将其解释为字符串。

您的最终 Razor 标记应如下所示:

<input id="btnAdd" type="button" value="Add" onclick="AddTextBox(JSON.parse('@Html.Raw(HttpUtility.JavaScriptStringEncode(Json.Serialize(Item).ToString()))'))"/>

继续阅读以更深入地了解如何在未来解决这些类型的问题,以及为什么每个步骤都是必要的。

调试

在深入研究之前,有必要退后一步重新审视一些故障排除原则。请记住,ASP.NET Core MVC 只是呈现 HTML 页面。之后,由浏览器来解析和执行 HTML 和 JavaScript。当您将 Razor、HTML 和 JavaScript 组合在同一行中,但只查看 JavaScript 生成的错误时,很容易忽略潜在问题。鉴于此,您要做的是在浏览器中查看源代码以查看正在生成的 HTML。

问题 #1:序列化类

最直接的问题是,当您调用 @Html.Raw(Item) 时,将调用 ItemToString() 方法来创建 Student 对象的字符串表示.如果您的 Student 对象是一个类,这将只是类的完全限定名称(例如,MyNamespace.Student)。

这将输出如下内容:

<input id="btnAdd" type="button" value="Add" onclick="AddTextBox(JSON.parse(MyNamespace.Student))"/>

这显然不是有效的 JSON,也不包含您的任何数据。要解决此问题,您需要在 Item 中包装对 Json.Serialize() 的调用,这会将其从 C# 对象序列化为 JSON 字符串:

<input id="btnAdd" type="button" value="Add" onclick="AddTextBox(JSON.parse(@Html.Raw(Json.Serialize(Item))))"/>

这将输出更接近您想要的内容:

<input id="btnAdd" type="button" value="Add" onclick="AddTextBox(JSON.parse({"Id"=1,"name":"John"}))"/>

问题 #2:编码 JSON

如果您尝试执行上述代码,您将遇到 JavaScript 错误,例如:

<块引用>

未捕获的语法错误:意外的输入结束

你看到问题了吗? Id 周围的引号将关闭您的 onclick 处理程序,导致标记格式错误。从浏览器的角度来看,它最终会看到以下属性,后面是无效标记:

  • id:btnAdd
  • 输入:button
  • 值:Add
  • 点击:AddTextBox(JSON.parse('{

要解决此问题,您需要对 JSON 字符串进行编码,以便将其嵌入到 JavaScript 调用中。幸运的是,ASP.NET Core 为我们提供了 HttpUtility.JavaScriptStringEncode() 方法来做到这一点:

<input id="btnAdd" type="button" value="Add" onclick="AddTextBox(JSON.parse(@Html.Raw(HttpUtility.JavaScriptStringEncode(Json.Serialize(Item).ToString()))))"/>
<块引用>

注意: JavaScriptStringEncode() 方法需要一个字符串,所以我们需要在 ToString() 调用上调用 Json.Serialize(),否则会输出一个 {{1} } 对象。

现在将输出如下内容:

IHtmlContent

问题 #3:转换为 JSON 对象

这里还是有问题。 <input id="btnAdd" type="button" value="Add" onclick="AddTextBox(JSON.parse({\&quot;Id\&quot;=1,\&quot;name\&quot;:\&quot;John\&quot;}))"/> 方法需要一个 string,但我们传递给它的是原始 JSON 符号。因此,如果您执行此代码,您现在将收到原始错误的变体:

<块引用>

未捕获的语法错误:无效或意外的令牌

这可以通过简单地将 JSON 包裹在撇号中来解决,表示它是一个字符串:

JSON.parse()

现在将输出如下内容:

<input id="btnAdd" type="button" value="Add" onclick="AddTextBox(JSON.parse('@Html.Raw(HttpUtility.JavaScriptStringEncode(Json.Serialize(Item).ToString()))'))"/>

如果您点击此元素,这最终应该会起作用——当然,前提是您的 <input id="btnAdd" type="button" value="Add" onclick="AddTextBox(JSON.parse('{\&quot;Id\&quot;=1,\&quot;name\&quot;:\&quot;John\&quot;}'))"/> 运行正常。

结论

如顶部所述,在使用 Razor、HTML 和 JavaScript 时,您确实需要密切关注从 Razor 页面呈现的 HTML,然后再由浏览器解析或由 JavaScript 执行引擎。在这种情况下,大多数问题源于浏览器或 JavaScript 引擎无法正确解析的格式错误的标记。