asp.net-mvc - 在 MVC4 中使用 JsonConvert.SerializeObject 清理输入?

标签 asp.net-mvc asp.net-mvc-4 knockout.js json.net

长话短说,我试图对 JsonConvert.SerializeObject 的输出进行清理,而不必修改已保存数据的内容。

我正在开发一个在 View 中具有以下标记的应用程序:

                 <textarea data-bind="value: aboutMe"></textarea>

如果我保存以下文本,则会遇到问题:

                 <script type="text/javascript">alert("hey")</script>

我在 FF 中遇到的错误:

enter image description here

有问题的渲染文本的相关部分:

$(document).ready(ko.applyBindings(new MyProfileVm({"profileUsername":"admin","username":"Admin","aboutMe":"alert(\"hey\")","title":"Here's a short self-bio! :)","thumbnail":"/image/l4lSe.jpg","locationZip":"22182","locationName":"Vienna, VA"

最后 - 在我的观点的底部:

<script type="text/javascript">
    $(document).ready(ko.applyBindings(new MyProfileVm(@Html.Raw(JsonConvert.SerializeObject(Model, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() })))));
</script>

在这里,我将从 MVC Controller 获取的模型传递到 js ViewModel 中,以进行 knockout 以映射到可观察的数据。原始编码似乎是问题所在,但我不确定如何处理它。

需要明确的是,我从服务器获取数据,并将其输出到客户端,这会弄乱 JSON/KO 组合。

最佳答案

问题是你不能有一个结束 </script> JavaScript 字符串文字中的标记,因为浏览器将其解释为脚本 block 的结尾。另请参阅: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 View 模型的 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 .

关于asp.net-mvc - 在 MVC4 中使用 JsonConvert.SerializeObject 清理输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19747846/

相关文章:

asp.net - 使用 Html.EditorFor 生成具有特定行数和列数的 textarea

controller - 基类中的 ExecuteCore() 在 MVC 4 beta 中未触发

javascript - Ajax 响应没有改变我的 View 模型

javascript - 使用 Knockout 嵌套表格

c# - HttpContext.Current 未在 MVC 4 项目中解析

asp.net-mvc - ASP.NET MVC 服务器端文件上传进度计算器

c# - MVC 中图像大小逻辑的正确位置是什么

c# - WMV 流媒体文件大小限制

html - bool 计算属性为 false/true 时的 knockoutjs css 绑定(bind)值

c# - 从默认的 mvc 应用程序数据库中删除用户