使用jQuery ajax请求的ASP.NET MVC模型绑定

4

我在我的MVC代码中有一个服务器端对象,看起来像这样:

class Person
{
  public long Id { get; set; }

  public string Name { get; set; }

  public IList<Friend> Friends { get; set; } 
}

class Friend
{
  public long Id { get; set; }

  public string Name { get; set; }
}

从jQuery客户端,我正在进行ajax请求并发送以下数据(为了便于阅读而引入了换行符):

var personId = $(...
var personName = $(...

var friends = []; // array of associative arrays

for (var i = 0; i < _friends.length; i++) // _friends is is a global array object and is different from friends below
{
  var friendId = $(...
  var friendName = $(...)

  friends[i] = { 'Id' : friendId, 'Name' : friendName };
}

...等等,以便将值放入变量中。

请注意,我正在发送应该放入Person.Friends中的内容,即一个JavaScript数组,其中数组的每个元素都是一个关联列表,其属性与服务器端的Friend类相同。

这是我的ajax请求:

$.ajax('/Strings/JsonCreateNew', 
  { 
    cache: false, async: false, type: 'POST', 
    data: { 
        'Id' : personId, 
        'Name' : personName, 
        'Friends' : friends}, 
    dataType: 'json', 
    error: SaveNewFriendClientSideHandler.OnError, 
    success: SaveNewFriendClientSideHandler.OnSuccess 
  });

在我的控制器中,只要我有一个FormCollection来接收数据,我就可以获取所有数据,但我想绑定到强类型的Person对象上,因此,如果我将我的控制器定义更改为:
[HttpPost]
public ActionResult JsonCreateNew(FromCollection person)
{
  // I get all the data in the person.AllKeys property
  return new EmptyResult();
}

to:

[HttpPost]
public ActionResult JsonCreateNew(Person person)
{
  // the default ASP.NET MVC model binder isn't able to bind to this
  // in fact, the routing module does not even route the request to this
  // action, so this action never gets fired.
  return new EmptyResult();
}

我仍然可以获取所有数据,但我真的很担心 IList<Friend>
它以数组形式在 Person 对象中接收,具有正确数量的 Friends 对象和正确的属性名称(NameId),但每个 Friend 对象的两个属性值(NameId)都是 null 或 0,即使客户端发送了值也不会初始化。
请帮忙。
3个回答

9

MVC中存在一个bug,他们拒绝修复,即如果集合属性名称以类型名称开头,则不会绑定。请修改。

    public IList<Friend> Friends { get; set; } 

致:

    public IList<Friend> Biscuits { get; set; } 

这只是暂时的。它会起作用。


太酷了!听起来不错。我会尝试一下并回复的。 :-) - Water Cooler v2
将它重命名为MyFriends是否可行?这样就足以改变属性,使其不再以类型名称开头... - jrista
我不记得是开头还是结尾了。但是试一下吧。 - regisbsb

0
你需要指定内容类型:contentType: "application/json"。@MohammadRB的解决方案包含了它,但即使你不将post数据转换为字符串,它也应该能正常工作。

-1

我认为它会起作用:

var p = { 'Id' : personId, 'Name' : personName, 'Friends' : friends };
$.ajax('/Strings/JsonCreateNew', 
  { 
    type: 'POST', 
    data: JSON.Stringify({ person : p }), 
    contentType : "application/json",
    dataType: 'json', 
    error: SaveNewFriendClientSideHandler.OnError, 
    success: SaveNewFriendClientSideHandler.OnSuccess 
  });

如果您只需要迭代它们,我更喜欢使用IEnumerable<>而不是IList<>

编辑 测试用例:

var friends = new Array();
friends.push({ Id: "1", Name: "A" });
friends.push({ Id: "2", Name: "B" });
var p = { 'Id': 5, 'Name': "Mohammad", 'Friends': friends };

$(document).ready(function () {

  $.ajax('/Home/JsonCreateNew',
  {
      type: 'POST',
      data: JSON.stringify({ person: p }),
      contentType: "application/json",
      dataType: 'json',
      error: function () { alert("f"); },
      success: function () { alert("s"); }
  });

});

@WaterCoolerv2 你必须在你的ajax请求中添加 'contentType: "application/json"' 和 'JSON.stringify()',当我删除它们时,服务器也会返回null值。 - MRB
对我来说,控制台报告JSON.Stringify不是一个函数。我需要包含什么才能获取JSON对象? - Water Cooler v2
2
@WaterCoolerv2 你用的是哪个浏览器?(在 stringify 中你是否使用了小写的 s,这可能是一个拼写错误) - MRB
我太蠢了。谢谢,当我发表最后一条评论时,我发现了错误的大写。非常感谢。然而,现在即使JSON.stringify函数工作正常,无论我接收一个FormCollection还是一个Person对象,服务器端接收到的数据仍然是一个空对象。 - Water Cooler v2
@WaterCoolerv2 很抱歉,我无法理解您的问题。如果您是从表单中收集数据,为什么不在表单上使用 serialize 方法呢? - MRB
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接