I have built an array of objects in JavaScript and want to post them back to the server via Ajax (Im using jQuery)
The JavaScript object array looks like this:
var columns = [
    { name: 'col 1', source: 'whatever', hidden: false, width: 50 },
    ...
];
Im posting it back like this:
$.post('/MyController/MyAction', { 'columns': columns });
On the controller action Im currently getting this:

I have a c# object called JqColumn that I want to bind the post into, it looks like this:
public class JqGridColumn
{
    public string name;
    public string source;
    public int width;
    public bool hidden;
}
So I thought that adding a parameter in the controller action of type JqGridColumn[] columns would automatically bind the posted data, but it doesn't (it generates a array, with the correct number of elements, but each item in the array has blank values)
Can anyone tell me what Im doing wrong? Thanks!
UPDATE
At present, I am manually binding the items in my controller action as follows:
    public void ColumnChooser(JqGridColumn[] columns)
    {
        for (int i = 0; i < columns.Length; i++)
        {
            columns[i].hidden = bool.Parse(Request.Form["columns[" + i + "][hidden]"]);
            columns[i].width = int.Parse(Request.Form["columns[" + i + "][width]"]);
            columns[i].name = Request.Form["columns[" + i + "][name]"];
            columns[i].source = Request.Form["columns[" + i + "][source]"];
        }
        return;
    }
...which works fine, but I'd really like to know the .Net MVC (correct) way to do it!
Since you didn't register a specific ModelBinder for the JqGridColumn type, the DefaultModelBinder will be used. But:
It won't bind Fields, only public Properties.
The expected format for Array binding is columns[0].name while you're actually posting columns[0][name].
The problem could be solved easily if you'll simply send your columns in JSON format instead of Name-Value-Pairs:
$.ajax({
    url: '/MyController/MyAction',
    method: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({ columns: columns })
});
Yet, if you don't like to change your class, you could register a ModelBinder specific for JqGridColumn and have it working even with Fields and current jQuery serialization:
public class JqGridColumnBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        string name = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + "[name]").AttemptedValue;
        string source = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + "[source]").AttemptedValue;
        int width = (int)bindingContext.ValueProvider.GetValue(bindingContext.ModelName + "[width]").ConvertTo(typeof(int));
        bool hidden = (bool)bindingContext.ValueProvider.GetValue(bindingContext.ModelName + "[hidden]").ConvertTo(typeof(bool));
        return new JqGridColumn
        {
            name = name,
            source = source,
            width = width,
            hidden = hidden
        };
    }
}
Then register it in App_Start/ModelBindingConfig.cs:
binders.Add(typeof(JqGridColumn), new JqGridColumnBinder());
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With