【问题标题】:KnockOutJs object not postingKnockOutJs 对象未发布
【发布时间】:2011-12-17 01:52:12
【问题描述】:

我正在处理一个 KnockOutJs 示例,并且在使用 MVC3 时遇到了一些发布问题。使用整页回发时,我的示例正确发布。当我尝试使用 jQuery Ajax 帖子保存时,我可以在 using Firebug NET 查看器中看到帖子:

{ 礼物:[{"GiftId":0,"Title":"sad","Price":3}] }

当我在MVC3的ModelBinder中查看ControllerContext时,表单参数为空,json没有绑定。关于正在发生的事情有什么想法吗?

我尝试了许多配置,但这里是 jQuery 发布代码(当前硬编码为静态值):

...

            $.ajax({
        url: "/Home/PartialUpdate", 
        type: 'POST', 
        cache: false,
        data:   '{ gifts:[{"GiftId":0,"Title":"sad","Price":3}] }', //ko.toJSON({ gifts: this.gifts }),   
        dataType: 'json' ,
        contentType: "application/json;",
        success: function(result){
            alert(result);
            var data = ko.utils.parseJson(result); 
            this.gifts =  ko.observableArray(data) ;
        },
        error:function(xhr,err){ 
            alert("readyState: " + xhr.readyState+"\nstatus: "+xhr.status); 
            alert("responseText: " + xhr.responseText);
        }
        });

编辑:这里是 Ajax 更新代码的 MVC3 操作代码

[HttpPost]
public JsonResult PartialUpdate ([FromJson] IEnumerable<Gift> gifts)
{
    gifts = gifts ?? new List<Gift>();
    using (var context = new KnockOutContext())
    {
        // Add record if not in DB
        foreach (var gift in gifts )
        {
            context.Entry(gift).State = (gift.GiftId == 0) ? EntityState.Added : EntityState.Modified;
        }

        // Delete records if not in ViewModel
        foreach (var dbGift in context.Gifts)
        {
            if (gifts.SingleOrDefault(c => c.GiftId == dbGift.GiftId) == null)
                context.Gifts.Remove(dbGift);
        }
        context.SaveChanges();
    }
    return GetGifts_Json();
}

以及有效的完整回发代码(来自 Steve Sanderson 在 http://blog.stevensanderson.com/2010/07/12/editing-a-variable-length-list-knockout-style/)

[HttpPost]
public ActionResult Index([FromJson] IEnumerable<Gift> gifts)
{
    SaveGifts(gifts);
    return RedirectToAction("Index");
}

使用此自定义模型绑定器:

        public class FromJsonAttribute : CustomModelBinderAttribute
        {
            private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer();

            public override IModelBinder GetBinder()
            {
                return new JsonModelBinder();
            }

            private class JsonModelBinder : IModelBinder
            {
                public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
                {
                    var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
                    if (string.IsNullOrEmpty(stringified))
                        return null;
                    return serializer.Deserialize(stringified, bindingContext.ModelType);
                }
            }
        }

【问题讨论】:

  • 您能从 MVC 添加您的操作代码吗?
  • 自 MVC2 以来,您不需要 [FromJson] 属性。
  • 使用dataType: 'json',您无需在回调中解析json。 Jquery 会为你做这件事。
  • 如果我删除 [FromJson],这两个版本都不起作用。回发版本在绑定中有错误{“从类型'System.String'到类型'koListEditor.Models.Gift'的参数转换失败,因为没有类型转换器可以在这些类型之间转换。”}。这个项目是从 MVC2 开始的,所以它的配置可能有问题。
  • 您需要使用注释掉的 ko.toJSON 作为 data 参数。

标签: jquery asp.net-mvc knockout.js


【解决方案1】:

我猜你是从 Steve 的下载开始的,它使用的是 MVC2。 MVC2 默认没有注册JsonValueProvider[FromJson] 属性旨在处理通过 ko.utils.postJson(完整回发)提交的 URL 编码的 JSON。当通过 AJAX 以正确的内容类型(在 MVC3 中)发布 JSON 时,这不是必需的。

因此,最简单的做法是将您的项目升级到 MVC 3(简单方法 here)并从部分更新中删除 [FromJson] 属性。

工作副本here

另外一件非常小的事情:您的静态数据当前是无效的 JSON ('{ gifts:[{"GiftId":0,"Title":"sad","Price":3}] }')。 gifts 需要是 "gifts"

【讨论】:

  • 谢谢,这行得通。为什么 ko.utils.postJson 需要 [FromJson] 绑定才能进行完整的回发?是否可以将其更改为使用内置的内置 MVC3 JsonValueProvider?
  • JsonValueProvider 仅适用于以 JSON 形式发布的数据。对于完整的回发,它需要额外的处理。您可以做的最好的事情是将 FromJson 属性转换为模型绑定器,然后将其注册到 global.asax.cs 以全局处理 IEnumerable,如该线程中所述:groups.google.com/d/topic/knockoutjs/3FEpocpApA4/discussion
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
  • 2014-07-05
  • 2013-02-04
  • 1970-01-01
  • 2016-09-10
  • 2022-01-04
相关资源
最近更新 更多