长话短说,我试图让JsonConvert.SerializeObject的输出被清理,而不必修改已保存数据的内容。
我正在开发一个在视图中包含以下标记的应用程序:
<textarea data-bind="value: aboutMe"></textarea>
如果我保存以下文字,我会遇到问题:
<script type="text/javascript">alert("hey")</script>
我在FF中遇到的错误:
违规渲染文字的相关部分:
(文档)$。就绪(ko.applyBindings(新 MyProfileVm({“profileUsername”:“admin”,“username”:“Admin”,“aboutMe”:“alert(\”hey \“)”,“title”:“这是一个 简短的自我生物! :) “ ”缩略图“: ”https://i.imgur.com/H1HYxU9.jpg“, ”locationZip“: ”22182“, ”LOCATIONNAME“:” 维也纳, VA“
最后 - 在我的观点的底部:
<script type="text/javascript">
$(document).ready(ko.applyBindings(new MyProfileVm(@Html.Raw(JsonConvert.SerializeObject(Model, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() })))));
</script>
在这里,我将我从MVC控制器获得的模型传递给js ViewModel,用于挖空以映射到可观察数据。 Raw编码似乎是个问题,但我不确定如何处理它。
要清楚,我从服务器获取数据,然后将其输出到客户端,这会破坏JSON / KO组合。
答案 0 :(得分:4)
问题是您不能在JavaScript字符串文字中包含结束</script>
标记,因为浏览器会将其解释为脚本块的结尾。另见:Script tag in JavaScript string
Asp.Net中没有内置函数可以在输出生成的脚本之前在服务器端处理它,您需要将</script>
替换为其他内容:
<script type="text/javascript">
$(document).ready(ko.applyBindings(new MyProfileVm(@Html.Raw(
JsonConvert.SerializeObject(Model,
new JsonSerializerSettings() {
ContractResolver = new CamelCasePropertyNamesContractResolver()
}).Replace("</script>", "</scripttag>")
))));
</script>
当然,如果你需要在多个地方使用它,你可以将这个逻辑转换为辅助/扩展方法,如:
public static class JavaScriptExtensions
{
public static string SerializeAndEscapeScriptTags(this object model)
{
return JsonConvert.SerializeObject(model,
new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
}).Replace("</script>", "</scripttag>");
}
}
并将其用于:
@using YourExtensionMethodsNamespace
<script type="text/javascript">
$(document).ready(ko.applyBindings(new MyProfileVm(@Html.Raw(
Model.SerializeAndEscapeScriptTags()))));
</script>
在Knockout视图模型的JavaScript端,您需要在使用前替换</script>
标记:
var MyProfileVm = function(data) {
//...
this.aboutMe = ko.observable(
// you need `"</scr"+ "ipt>"` because of the above mentioned problem.
data.aboutMe.replace(/<\/scripttag>/g, "</scr"+ "ipt>"));
}
当然你也可以为此创建一个辅助函数,如:
function fixScriptTags(data) {
for(var prop in data) {
if (typeof(data[prop]) == "string") {
data[prop] = data[prop].replace(/<\/scripttag>/g, "</scr"+ "ipt>");
}
//todo check for complex property values and call fixScriptTags recursively
}
return data;
}
并将其用于:
ko.applyBindings(new ViewModel(fixScriptTags(data)));
演示JSFiddle。
答案 1 :(得分:1)
我遇到了类似的问题,它来自于使用knockout.js来获取<textarea>
的输入,就像你一样。在“创建”部分,一切都很好,但是一旦我通过@Html.Raw(...)
将数据放回到一个动作中,它就会包含打破json字符串的换行符和回车符。
所以我添加了这样的东西:
// Regex to replace all unescaped (single) backslashes in a string
private static Regex _regex = new Regex(@"(?<!\\)\\(?!\\)", RegexOptions.Compiled);
(我知道它不会处理“\\\”,但这不会出现在淘汰赛中)
然后我构建我的匿名类并执行此操作:
var coJson = JsonHelper.Serialize(co);
var coJsonEsc = _regex.Replace(coJson, @"\\")
也许这可以帮到你。我通过打破剃刀视图并查看字符串找到了它。 这个问题也出现在unesacped标签(\ t)和可能的其他转义序列中。