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());