在MVC4中使用JsonConvert.SerializeObject清理输入?

SB2*_*055 4 asp.net-mvc json.net asp.net-mvc-4 knockout.js

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

我正在开发在视图中具有以下标记的应用程序:

                 <textarea data-bind="value: aboutMe"></textarea>
Run Code Online (Sandbox Code Playgroud)

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

                 <script type="text/javascript">alert("hey")</script>
Run Code Online (Sandbox Code Playgroud)

我在FF中得到的错误:

在此处输入图片说明

违规渲染文本的相关部分:

$(document).ready(ko.applyBindings(new MyProfileVm({“ profileUsername”:“ admin”,“ username”:“ Admin”,“ aboutMe”:“ alert(\” hey \“)”,“ title”: “这是一个简短的自我简介!:)”,“缩略图”:“ https://i.imgur.com/H1HYxU9.jpg ”,“ locationZip”:“ 22182”,“ locationName”:“维也纳,弗吉尼亚州”

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

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

在这里,我将从MVC控制器获得的模型传递给j​​s ViewModel,以进行剔除,以映射到可观察的数据中。Raw编码似乎是问题所在,但我不确定该如何处理。

明确地说,我正在从服务器获取数据,并将其输出到客户端,这将构成JSON / KO组合。

nem*_*esv 5

问题在于,</script>JavaScript字符串文字中不能包含结束标记,因为浏览器会将其解释为脚本块的结尾。另请参阅:JavaScript字符串中的脚本标签

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>
Run Code Online (Sandbox Code Playgroud)

当然,如果您需要在多个地方使用此方法,则可以将此逻辑移到辅助方法/扩展方法中,例如:

public static class JavaScriptExtensions
{
    public static string SerializeAndEscapeScriptTags(this object model)
    {
        return JsonConvert.SerializeObject(model,
            new JsonSerializerSettings()
                {
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                }).Replace("</script>", "</scripttag>");
    }
}
Run Code Online (Sandbox Code Playgroud)

并用于:

@using YourExtensionMethodsNamespace

<script type="text/javascript">
        $(document).ready(ko.applyBindings(new MyProfileVm(@Html.Raw(
            Model.SerializeAndEscapeScriptTags()))));
</script>
Run Code Online (Sandbox Code Playgroud)

并且在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>"));
}
Run Code Online (Sandbox Code Playgroud)

当然,您也可以为此创建一个辅助函数,例如:

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;
}
Run Code Online (Sandbox Code Playgroud)

并用于:

ko.applyBindings(new ViewModel(fixScriptTags(data)));
Run Code Online (Sandbox Code Playgroud)

演示JSFiddle