ASP.NET核心Razor页面:将值从Foreach传递到JavaScript函数



我正试图将值从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. 使用Json.Serialize()Student对象(Item(序列化为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
  • onclick: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()方法需要一个字符串,因此我们需要在Json.Serialize()调用上调用ToString(),否则它将输出一个IHtmlContent对象。

这将输出如下内容:

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

问题#3:转换为json对象

这里仍然存在问题。JSON.parse()方法需要一个字符串,但我们传递的是原始JSON表示法。因此,如果您执行此代码,您现在将收到原始错误的变体:

未捕获的SyntaxError:无效或意外的令牌

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

<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;}'))"/>

如果您点击这个元素,这应该最终会起作用——当然,假设您的AddTextBox()运行正常。

结论

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

最新更新