7

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:

enter image description here

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!

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 Commented Apr 23, 2014 at 11:22
  • Tried and still no joy I'm afraid... :( 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. Commented Apr 24, 2014 at 8:56

3 Answers 3

10

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());
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks :) Didn't want to use a custom model binder, so the JSON.stringify for the win!
0

It's because your JqGridColumn object needs properties, not fields. see this question for reference:

ASP.net MVC - Model binding excludes class fields?

3 Comments

Thanks for the reference. Unfortunately, even when the JqGridColumn variables are changed to properties, they still don't get bound.
You could try changing it to a List<JqGridColumn> instead of an array. I don't think it'll help as your getting the right number of items.
On the off chance that it might work, I tried changing to a List<JqGridColumn> but still no binding :(
0

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'); }
});

1 Comment

Even with this change, the form post is still seen the same by the controller.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.