Reputation: 1306
I'm having a an odd problem with MVC3 and the model binding. When I post a JSON object to my controller the model binder can't create a typed object out of it at all. All the properties are the default (i.e. empty strings)
However if I create an instance on the server, and send it as a JSON action result the data on the wire looks identical.
I've tried with
$.ajaxSettings.traditional = true;
and it makes no difference
As an example if I post
{"RoutineName":"My new routine","Routines":[{"DayName":"Monday","Items":[21,31]}]}
The model binder fails, but coming from the server the data looks like
{"RoutineName":"Routine From Code","Routines":[{"DayName":"Monday","Items":[1,2]},{"DayName":"Tuesday","Items":[]}]}
The html used to generate this looks like
$('#submitRoutine').click(function () {
var routines = [];
$('.DayName').each(function (index, item) {
var $item = $(item);
var name = $item.html();
var routineItems = [];
$($item.attr('href')).find('.itemId').each(function () {
routineItems.push(parseInt($(this).val(), 10));
});
routines.push({
DayName: name,
Items: routineItems
});
});
var routine = {
RoutineName: $('#routineName').val(),
Routines: routines
};
$.ajaxSettings.traditional = true;
$.post('/Machine/CreateRoutine', JSON.stringify(routine),function (data) {},'json');
});
So it looks like model binding from a typed object to JSON is ok, but coming back the other way isn't. Is there something I've missed?
The models are in F#
type RoutineDayViewModel() =
let mutable _name = String.Empty
let mutable _items = new ResizeArray<int>()
member x.DayName with get() = _name and set value = _name <- value
member x.Items with get() = _items and set value = _items <- value
type RoutineViewModel() =
let mutable _name = String.Empty
let mutable _routines = new ResizeArray<RoutineDayViewModel>()
member x.RoutineName with get() = _name and set value = _name <- value
member x.Routines with get() = _routines and set value = _routines <- value
EDIT: I've also tried with the following C# classes and get the same result
public class RoutineDayViewModel
{
public string DayName { get; set; }
public List<int> Items{ get; set; }
}
public class RoutineViewModel
{
public string RoutineName { get; set; }
public List<RoutineDayViewModel> Routines { get; set; }
}
I've also added the following to the global.asax
ValueProviderFactories.Factories.Add(new JsonValueProviderFactory())
Thanks
Upvotes: 5
Views: 3251
Reputation: 1038710
You need to set the request content type to application/json
if you intend to send a JSON formatted request which is what you are doing with the JSON.stringify
method. So instead of:
$.post('/Machine/CreateRoutine', JSON.stringify(routine),function (data) {},'json');
you could use:
$.ajax({
url: '/Machine/CreateRoutine',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(routine),
success: function (data) {
}
});
With this you don't need to set $.ajaxSettings.traditional
nor you should be adding any JsonValueProviderFactory
in your Global.asax as this provider is already added by default in ASP.NET MVC 3.
Upvotes: 8
Reputation: 1306
I solved it using Nick Riggs Postify javascript code
http://www.nickriggs.com/posts/post-complex-javascript-objects-to-asp-net-mvc-controllers/
Upvotes: 2