我正试图将值从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; }
}
您需要做三件事来解决此问题:
- 使用
Json.Serialize()
将Student
对象(Item
(序列化为JSON - 使用
HttpUtility.JavaScriptStringEncode()
将JSON编码为JavaScript字符串 - 用撇号包装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)
时,将调用Item
的ToString()
方法来创建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({"Id"=1,"name":"John"}))"/>
问题#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('{"Id"=1,"name":"John"}'))"/>
如果您点击这个元素,这应该最终会起作用——当然,假设您的AddTextBox()
运行正常。
结论
如上所述,在使用Razor、HTML和JavaScript时,在浏览器解析或JavaScript引擎执行之前,您确实需要密切关注Razor页面中呈现的HTML。在这种情况下,这些问题大多源于浏览器或JavaScript引擎无法正确解析的格式错误的标记。