Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

MVC Complex Model Postback: Bind Field to JSON string

, 20 Jul 2013
Rate this:
Please Sign up or sign in to vote.
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):

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

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

Controller is trivial:

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.

<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:

    public class JsonBindableAttribute : Attribute
    {
    }

… and a custom model binder:

    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:

    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)

Share

About the Author

m_kramar

Australia Australia
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.140922.1 | Last Updated 20 Jul 2013
Article Copyright 2013 by m_kramar
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid