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!
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!
Share Improve this question edited Apr 23, 2014 at 11:44 Jimbo asked Apr 23, 2014 at 10:54 JimboJimbo 23k44 gold badges125 silver badges162 bronze badges 3- Have you tried making the fields on your JqGridColumn object into properties (ie, add a get & set) as it sounds the the model binder can't find the fields – Simon Halsey Commented Apr 23, 2014 at 11:22
- Tried and still no joy I'm afraid... :( – Jimbo Commented Apr 23, 2014 at 11:42
- Have you tried using a WebApi Controller, the model binding might be handled differently using the WebAPI Controller as the default MVC binding (i think) depends on HTML Elements being posted back in a FormCollection. – Patrick Magee Commented Apr 24, 2014 at 8:56
3 Answers
Reset to default 10Since 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 postingcolumns[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());
It's because your JqGridColumn object needs properties, not fields. see this question for reference:
ASP MVC - Model binding excludes class fields?
try post back with the traditional : true setting and dataType: json
$.ajax({
url: '/MyController/MyAction',
method: 'POST',
traditional: true,
dataType: json
data: columns ,
sucess: function () { alert('Success'); }
});