1

I have a json array containing integers and objects.

[1,2,3,{Name:"russia",Value:6},{Name:"usa",Value:"8"}]

I also have the following server-side class

class country {
  string Name;
  int Value;
}

How should I go about binding the json array to a server-side parameter ? I tried using a List<object> on server. It binds the integers fine but no country instances are created. Instead, primitive objects are created and added to the list.

Thanks.

2
  • Is there a way to do it by creating a custom value provider ? Commented Jun 22, 2011 at 19:54
  • This is especially important for passing data to Flot graphs - the entire data series is a mixed type array for which the first solution below would never work. Commented Jul 9, 2011 at 19:27

2 Answers 2

1

You could try something like this:

Format your controller action to accept a List<int> for your integer values and a List<Country> for your Country objects.

public ActionResult Index(List<int> intValues, List<Country> countryValues)

Then build your JSON like so that it contains and array of integers and an array of country objects:

var postData = {
    intValues: [1, 2, 3],
    countryValues: [
        { Name: 'USA', Value: 6 },
        { Name: 'Russia', Value: 8 }
    ]
};

And perform a simple AJAX call to send the data

$(function() {
    $.ajax({
        type: 'POST',
        url: "@Url.Action("Create")",
        contentType: "application/json",
        data: JSON.stringify(postData)
    });
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the reply Gram. I'm aware of this solution. I was wondering if there's a way of overriding the default model binding behavior to get the List<object>. I'm fine as long as country instances are created and upcasted to "object".
1

Okay, I solved it at last. I created a custom model binder derived from the default model binder to accomplish this. Here's the code.

public ActionResult Home(NonHomogeneousList input)

[ModelBinder(typeof(CustomModelBinder))]
class NonHomogeneousList : List<object>

public class CustomModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            NonHomogeneousList model = (NonHomogeneousList)base.BindModel(controllerContext, bindingContext);
            if (model.Members != null)
            {
                IModelBinder countryBinder = Binders.GetBinder(typeof(Country));

            // find out if the value provider has the required prefix
            bool hasPrefix = bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName);
            string prefix = (hasPrefix) ? bindingContext.ModelName + "." : "";

            for (var i = 0; i < model.Count; i++)
            {
                var member = model.Members[i];
                if (member.GetType().Equals(typeof(object)))
                {
                    var subKey =  CreateSubIndexName( prefix , i);
                    ModelBindingContext innerContext = new ModelBindingContext()
                    {
                        ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(Country)),
                        ModelName = subKey,
                        ModelState = bindingContext.ModelState,
                        PropertyFilter = bindingContext.PropertyFilter,
                        ValueProvider = bindingContext.ValueProvider,
                    };
                    var country = countryBinder.BindModel(controllerContext, innerContext);
                    model.Members[i] =  country;
                }
            }
        }
        return model;
    }
}
}

Comments

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.