问题
I have a server side object in my MVC code that looks like this:
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; }
}
From the jQuery client, I am making an ajax request and sending the following data (line breaks introduced for readability):
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 };
}
... and so on to get values into variables
Please observe that I am sending what should go into Person.Friends
, the IList<T>
as a JavaScript array where each element of the array is an associative list that has properties just like the server side Friend
class.
Here's my ajax request:
$.ajax('/Strings/JsonCreateNew',
{
cache: false, async: false, type: 'POST',
data: {
'Id' : personId,
'Name' : personName,
'Friends' : friends},
dataType: 'json',
error: SaveNewFriendClientSideHandler.OnError,
success: SaveNewFriendClientSideHandler.OnSuccess
});
In my controller, as long as I have a FormCollection
to receive the data, I get all my data, but I'd like to bind to the strongly typed Person object, so if I change my controller definition from:
[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();
}
I still do get all my data but I am really still concerned about the IList<Friend>
.
It is received in the Person
object as an array that has the correct number of Friends
objects with the right property names (Name
and Id
) but the values of both the properties of each Friend
object are null
or 0, i.e. not initialized even when there are values being sent by the client.
Please help.
回答1:
There is a bug in MVC they refuse to fix that if the colection property name begins with the type name it does not bind. Change
public IList<Friend> Friends { get; set; }
To:
public IList<Friend> Biscuits { get; set; }
just temporary. It will work.
回答2:
You have to specify the content type: contentType: "application/json"
. @MohammadRB solution contains it, but it should work even if you don't stringify the post data.
回答3:
I think it will work:
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
});
Also i prefer IEnumerable<> instead of IList<> if you only want iterate over them
Edit Test case :
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"); }
});
});
来源:https://stackoverflow.com/questions/19299008/asp-net-mvc-model-binding-with-jquery-ajax-request