如何使用jQuery发布复杂对象(包含复杂对象数组)的数组

问题描述:

我想使用jQuery发布一些具有ID和某些类别的产品。但是,当我添加Categories时,出现以下错误:Microsoft.Web.Mvc.DataAnnotations.DataAnnotationsModelBinder.BindProperty(NullReferenceException)。如何使用jQuery发布复杂对象(包含复杂对象数组)的数组

不应该默认的ModelBinder能够绑定这个(没有ActionFilter或自定义ModelBinder)?

我试图应用一个ActionFilter(反序列化),我发现在另一个SO线程,但它永远不会运行。我也试过用jQuery.ajaxSettings.traditional = true,jQuery 1.3.2和1.4.2。在我发现的其他例子中,他们只是发布ID,Name等,而不是另一个复杂对象的数组。

任何想法?

public class Product 
{ 
    public int ID { get; set; } 
    public Category[] Categories { get; set; } 
} 

public class Category 
{ 
    public int ID { get; set; } 
} 

HTML

<input id="Product[0]_ID" name="Product[0].ID" type="hidden" value="9" /> 
<input id="Product[0]_Categories[0]_ID" name="Product[0].Categories[0].ID" type="hidden" value="99" /> 
<input id="Product[1]_ID" name="Product[1].ID" type="hidden" value="8" /> 
<input id="Product[1]_Categories[0]_ID" name="Product[1].Categories[0].ID" type="hidden" value="88" /> 

控制器

[JsonFilter(Parameter = "p")] 
public JsonResult GetProductPrice([Bind(Prefix = "Product")] Product[] p) 
{ 
    // TODO: Implement some checking... 
    return Json(true); 
} 

jQuery的

$.post(getProductPriceUrl, $("form").serializeArray(), function(data) { 
    $("#Price").html(data); 
}); 

JsonFilter

public class JsonFilter : ActionFilterAttribute 
{ 
    public string Parameter { get; set; } 
    //public Type JsonDataType { get; set; } 

    private JavaScriptSerializer serializer; 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     serializer = new JavaScriptSerializer(); 

     if (filterContext.HttpContext.Request.ContentType.Equals("application/json")) 
     { 
      string inputContent; 

      using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream)) 
      { 
       inputContent = sr.ReadToEnd(); 
      } 

      var result = serializer.Deserialize<Product>(inputContent); 
      filterContext.ActionParameters[Parameter] = result; 
     } 
    } 
} 

POST#1

__RequestVerificationToken=sz%2BLKCzTmdGMrH3TdOYipS5z%2BJ3uVyzBtJRZrruJoUohoGaH2O3DU5%2FcuU6hX1E%2F&Product%5B0%5D.ID=9&Product%5B0%5D.Categories%5B0%5D.ID=99&Product%5B1%5D.ID=8&Product%5B1%5D.Categories%5B0%5D.ID=88 

POST#2

__RequestVerificationToken=sz+LKCzTmdGMrH3TdOYipWTERHSdtCvGUhuw/dGIkgSL3rjcSLO7RJJN/rcssVwv&Product[0].ID=9&Product[0].Categories[0].ID=99&Product[1].ID=8&Product[1].Categories[0].ID=88 

POST#3

[{"name":"__RequestVerificationToken","value":"sz+LKCzTmdGMrH3TdOYipcqr8WKC2eL7CRS5BZUtwzD60WkqfnjdeAcO3DQg5ss6"},{"name":"Product[0].ID","value":"9"},{"name":"Product[0].Categories[0].ID","value":"99"},{"name":"Product[1].ID","value":"8"},{"name":"Product[1].Categories[0].ID","value":"88"}] 
+0

你不应该需要一个ActionFilter。你可以显示“POST”数据吗? – 2010-03-11 13:53:13

+0

呃,帖子1&2是常规键/值,“帖子”3是JSON。你打算做什么?为什么有两种方法?一般来说,首选MVC中的标准POST,因为JSON需要特殊处理。 – 2010-03-11 16:58:42

+0

我想使用一个标准的POST,但经过几个小时的测试,并没有得到它的工作。我开始怀疑这是可能的,所以我用这个解决方案阅读了一些SO线程后,尝试了JSON和“JsonFilter”。 – 2010-03-11 20:05:55

有两种方法我能想到的来完成发送一个复杂的对象图到目标的目标服务器连接正确。一种是你最初尝试的方式,那就是在html中表达关系。另一种是传递给子对象的部分视图。

因此,您需要为类别列表创建部分视图并将Product.categories传递给它。这应该照顾好你的线路。

这将是

@Html.Partial("_myCategoriesPartialView", Model.Categories) 

当然,这种观点会遍历集合。 我相信如果你想用html的方式做它,它会看起来像。

<input id="Product[0]_ID" name="Product[0].ID" type="hidden" value="9" /> 

应该

<input id="Product[0].ID" name="Product[0].ID" type="hidden" value="9" />, 

但肯定地告诉的方法是看Response.Form数据