3

如何将客户端函数序列化为 json 对象?(类似于剑道控制的工作方式)

这是我目前所拥有的......

看法:

@Html.TestControl(@<text>function(){ alert("test"); }</text>)

控制助手:

public static HtmlString TestControl<TModel>(this HtmlHelper<TModel> helper, Func<object, object> onSubmit)

{
    var obj = new {onSubmit = onSubmit.Invoke(null) };
    var jsonObj = new JavaScriptSerializer().Serialize(obj);
    return new HtmlString(string.Format("<script>var obj = {0};</script>", jsonObj));
}

输出:

<script>var obj = {"onSubmit":{}};</script>

期望的输出:

<script>var obj = {"onSubmit": function(){ alert("test"); }};</script>

我可以看到帮助器中 obj.onSubmit 的值是函数......但是我怎样才能让函数序列化并出现在 json 对象中(作为函数)?

更新:

首选使用 @<text> 定义匿名函数内联。我们使用具有这种语法的 Kendo 控件,目标是保持代码一致。

这是剑道控件语法的示例: http ://docs.kendoui.c​​om/api/wrappers/aspnet-mvc/Kendo.Mvc.UI.Fluent/UploadEventBuilder

4

4 回答 4

2

我花了更多时间四处搜索并找到了类似的帖子,但没有找到解决方案:

使用 C# 将函数序列化为 json 中的参数

JSON用函数参数序列化一个对象

最后使用 Json.net 库让它工作。使用 JRaw 类将生成一个带有定义为函数的 onSubmit 属性的 json 对象。

Json.net 文档:http: //james.newtonking.com/projects/json/help/html/SerializeRawJson.htm

更新的控制助手:

public static HtmlString TestControl<TModel>(this HtmlHelper<TModel> helper, Func<object, object> onSubmit)
{
    var obj = new { onSubmit = new JRaw(onSubmit.Invoke(null).ToString()) };
    var jsonObj = JsonConvert.SerializeObject(obj);
    return new HtmlString(string.Format("<script>var obj = {0};</script>", jsonObj));
}

输出:

<script>var obj = {"onSubmit":function(){alert("test");}};</script>

现在我可以在客户端调用 obj.onSubmit() 来调用该函数。

于 2013-05-28T19:57:20.550 回答
1

根据@ryan 的回答,我稍微升级到更像kendoUI。

public class TextBox : BaseControl
{
    [JsonProperty("onChange", NullValueHandling = NullValueHandling.Ignore)]
    [JsonConverter(typeof(JsFunctionConverter))]
    public Func<object, object> OnChange { get; set; }

    public override MvcHtmlString Render()
    {
        // Create html
        // <input />
        _tagBuilder = new TagBuilder("input");

        // Add script
        StringBuilder builder = new StringBuilder(base.Render().ToString());
        string script = @"<script>var {0} = {{name: '{0}', scope : angular.element($('#{0}')).scope(), options: {1}}}; textBox({0});</script>";

        BuildOptions();
        builder.AppendFormat(script, Name, JsonConvert.SerializeObject(this));
        return MvcHtmlString.Create(builder.ToString());
    }

这是 JsFunctionConverter:

public class JsFunctionConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof (string) || objectType == typeof (Func<object,object>);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JRaw jRawData;

        if (value.GetType() == typeof(Func<object, object>))
        {
            jRawData = new JRaw(((Func<object,object>)value).Invoke(null));
        }
        else
        {
            jRawData = new JRaw(value);
        }

        jRawData.WriteTo(writer);
    }
}

你可以像 KendoUI 那样做

var textBox = new TextBox
{
    OnChange = @<text>
                    function(e){

                            return e;
                    }
                </text>
};
于 2015-07-31T22:33:10.467 回答
0

只需将此 onSubmit 参数设为字符串并按原样使用其值。调用帮助程序时,您将不再需要文本标签。

于 2013-05-24T16:46:26.330 回答
0

您将服务器上的功能与客户端上的功能混淆了。您实际上是在服务器上执行 onSubmit 并将其结果放入您序列化为 json 的对象中。

反而:

将 TestControl 的第二个参数设为字符串。另外,不要序列化对象。相反,请手动创建您的 json。

public static HtmlString TestControl<TModel>(this HtmlHelper<TModel> helper, string onSubmit)
{
  string jsonObj = String.Format("{{ \"onSubmit\": {0} }}", onSubmit);
  return new HtmlString(string.Format("<script>var obj = {0};</script>", jsonObj));
}

然后你可以使用:

@Html.TestControl("function(){ alert('test'); }")

您的 jsonObj 将是:

{ "onSubmit": function(){ alert('test'); } }

最后,您的TestControl()方法将返回

<script>var obj = { "onSubmit": function(){ alert("test"); } };</script>
于 2013-05-25T01:17:31.643 回答