I am having trouble model binding a JSON array to a C# list in MVC 3.
I have an object called a DockState
. It looks like this:
[Serializable]
public class DockState
{
public bool Closed { get; set; }
public bool Collapsed { get; set; }
public string DockZoneID { get; set; }
public int ExpandedHeight { get; set; }
public Unit Height { get; set; }
public int Index { get; set; }
public Unit Left { get; set; }
public bool Pinned { get; set; }
public bool Resizable { get; set; }
public string Tag { get; set; }
public string Text { get; set; }
public string Title { get; set; }
public Unit Top { get; set; }
public string UniqueName { get; set; }
public Unit Width { get; set; }
}
My action method accepts a list of dock states, like this:
public JsonResult SaveDockStates(List<DockState> dockStates)
On the client I am building an array of JSON objects that contain all the same properties as the C# DockState
object. I am then assigning this array to a JSON object of its own with the property of the argument in the action method, like this:
function get_allDockStates()
{
var allRadDocks = []; // declare array.
var allRadControls = $telerik.radControls; // use telerik API to obtain all controls.
// loop through all telerik controls.
for (var i = 0; i < allRadControls.length; i++)
{
var element = allRadControls[i];
// Check if control is a rad dock element.
if (Telerik.Web.UI.RadDock && element instanceof Telerik.Web.UI.RadDock)
{
// Build a JSON object containing the same properties as the C# DockState
// object. Leaving out a couple that should just be null anyway. Add new
// JSON object to array.
Array.add(allRadDocks,
{
UniqueName: element._uniqueName,
DockZoneID: element._dockZoneID,
Width: element._width,
Height: element._height,
ExpandedHeight: element._expandedHeight,
Top: element._top,
Left: element._left,
Resizable: element._resizable,
Closed: element._closed,
Collapsed: element._collapsed,
Pinned: element._pinned,
Title: element._title,
Index: element._index
});
}
}
// Return the array.
return allRadDocks;
}
// This function is fired by the rad dock controls when they are moved.
function positionChanged(sender, e)
{
// obtain the array of dock states.
var dockStates = get_allDockStates();
// Make ajax call to MVC action method to save dock states.
jQuery.ajax({
data: { dockStates: dockStates },
type: 'POST',
dataType: 'json',
url: '/AjaxServices/DashboardService/SaveDockStates'
});
}
Unfortunately something rather odd happens when the AJAX call is made. It hits the action method and my List<DockState>
does have items in it.
http://www.codetunnel.com/content/images/dockStateListInstantiated.jpg
However, the items in the list are all default. Meaning all their values are the default values, not the ones submitted in the request.
http://www.codetunnel.com/content/images/dockStatesDefaultValues.jpg
I'm not sure why the list contains the correct number of items, but all items appear to be nothing more than instantiated. Their properties were not set to the values in the JSON array. The request definitely contains the right data, as shown here:
http://www.codetunnel.com/content/images/dockStatesFormData.jpg
Am I doing something wrong? Is the form data formatted incorrectly? Is there a problem with the default model binder?
Update (testing Darin Dimitrov's answer)
I discovered that JSON was being overridden by an unused old script. I have removed and now JSON.stringify
is working fine. Here is the request payload.
http://www.codetunnel.com/content/images/dockStatesJsonStringify.jpg
Much better. However now when I am debugging my list has zero items in it. This did not seem to fix the problem, though I appreciate the effort :)