Click here to Skip to main content
15,881,172 members
Articles / Multimedia / GDI
Technical Blog

MVC Complex Model Postback: Bind Field to JSON string

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
20 Jul 2013CPOL 13.2K   2   1
MVC Complex model postback: bind field to JSON string

Introduction

In my scenario, model had both simple fields directly bindable to input controls, and an array of complex objects that was constructed using fancy JavaScript. I had to submit the whole model using one form postback (no AJAX).

This is the model (the challenge here was to bind ComplexData):

C#
public class ComplexModel
{
    public string FirstName {get;set;}
    public string LastName {get;set;}

    [JsonBindable]
    public List<ComplexObject> ComplexData {get;set;}
}

Controller is trivial:

C#
public class ComplexController : Controller
{
    public ViewResult Save(ComplexModel model)
    {
        // save it
    }
}

View binds FirstName and LastName directly to inputs and ComplexData property is prepared just before form submit by stringifying the JSON object. Formatted JSON string is placed in a hidden field.

HTML
<script>
    $(document).ready(function () {
        $('form').submit(function () {
            $('input[name=ComplexData]').val(JSON.stringify(getMyComplexDataObject()));
        });
    }
</script>

<form>
    <input name='FirstName'/>
    <input name='LastName'/>
    <input type='hidden' name='ComplexData'/>
    <input type='submit' value='Save!' />
</form>

So the problem was to bind JSON string to the ComplexObject. The solution to the problem was to create custom attribute:

C#
public class JsonBindableAttribute : Attribute
{
}

… and a custom model binder:

C#
public class JsonPropBinder : DefaultModelBinder
{
    protected override object GetPropertyValue(ControllerContext controllerContext,
    ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor,
    IModelBinder propertyBinder)
    {
        if (propertyDescriptor.Attributes.OfType<Attribute>().
        Any(x => (x is JsonBindableAttribute)))
        {
            var value = bindingContext.ValueProvider.
            GetValue(bindingContext.ModelName).AttemptedValue;
            return JsonConvert.DeserializeObject
            (value, propertyDescriptor.PropertyType);
        }
        return base.GetPropertyValue(controllerContext, bindingContext,
                              propertyDescriptor, propertyBinder);
    }
}

… and finally register the binder:

C#
protected void Application_Start()
{
    ModelBinders.Binders.Add(typeof(ComplexModel), new JsonPropBinder());
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionThank you!!. Exactly what I need Pin
choi83012-Jun-15 8:48
choi83012-Jun-15 8:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.