List with datamodel won't get bound to json object

I've had this problem before and I've never solved it in a good way.

This is my JSON-object:

{ Targets: [{ Target: { Id: -1, EditUrl: editUrl}}] }

These are the models I use:

public class TargetList
{
    public List<Target> Targets { get; set; }
}

public class Target
{
    public int Id { get; set; }
    public string EditUrl { get; set; }
}

This is the action:

    [HttpPost]
    public PartialViewResult GetSpecifics(TargetList targetList)
    {
        //Code and stuff
    }

TargetList always turns out to be null. I've never been able to use lists like this even though it's supposed to work OOTB (right?). "Normal" data models with only properties and no lists work perfectly.

I saw some related Qs here and some of them suggested having traditional: true in the $.post. Doesn't work. I've stringified and not stringified the data to no avail. If not stringified when traditional is set to true, the json object just becomes Targets: [Object object] so I guess it has something to do with the post.

Can I manually bind my objects somehow? Override the factory in certain circumstances? I feel like I need more control over this function.

I am using MVC3, .NET4 and jQuery-1.7.2.

I'd really, really appreciate any help.

Answers


Not sure why your TargetList is not being deserialized properly. You could try creating a custom ModelBinder and then manually deserializing your JSON in the binder. This will keep your controller clean. I use Json.NET as a serializer on my project. Just create your own ModelBinder:

public class CustomModelBinder : IModelBinder
{
  public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
  {
    string inputContent;
    using (var sr = new StreamReader(controllerContext.HttpContext.Request.InputStream))
    {
      inputContent = sr.ReadToEnd();
    }
    //JsonConvert is part of Json.NET
    var result = JsonConvert.DeserializeObject(inputContent, bindingContext.ModelType);
    return result;
  }
}

Then in Global.asax.cs set your ModelBinder for TargetList:

protected void Application_Start()
{
  ModelBinders.Binders[typeof(TargetList)] = new CustomModelBinder();
}

You can also use the ModelBinder for any other Models that needs deserialization.


Target: is redundant. Json string representing your model should be

{"Targets":[{"Id":1,"EditUrl":"aaa"},{"Id":2,"EditUrl":"bbb"}]}

If you can, remove it from your Json string. Otherwise declare your classes as:

public class TargetList
{
    public List<Target1> Targets { get; set; }
}

public class Target1
{
    public Target2 Target;
}

public class Target2
{
    public int Id { get; set; }
    public string EditUrl { get; set; }
}

I tested with

string json = "{ Targets: [{ Target: { Id: -1, EditUrl: \"aaaa\"}}] }";
var validObj = new JavaScriptSerializer().Deserialize<TargetList>(json);

Need Your Help

Instantiated a class, but it appears referenced to null

grails groovy grails-2.0 groovy-2

I'm trying to instantiate an object and set a single attribute on it, which comes from a request parameter, like so :

OpenERP - OpenChatter and track_visibility fields datetime

python openerp utc openerp-7

I understand that with 'track_visibility' can generate a kind of log of changes in value, this works very well, but I've found problems with my time zone and datetime fields; as the value showing m...