Model Binding a json array containing different object types in Asp.Net MVC
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 bind开发者_开发问答s the integers fine but no country instances are created. Instead, primitive objects are created and added to the list.
Thanks.
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)
});
});
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;
}
}
}
精彩评论