Monday, August 10, 2009

MVC JSON Model Binder Attribute

Here it is folks: the Ultimate Ultimate* ASP.NET MVC JSON Model Binder!

Moving complex data structures from client to server used to be difficult, but not anymore! Just add the JsonBinder attribute to your action parameters, and this Custom ModelBinder will automatically detect the type and parameter name, and deserialize your complex JSON object to the data structure of your choice.

No configuration required, it works every time, it's PFM!**

* Yes, I said Ultimate twice.
** Pure Friendly Magic

JsonBinderAttribute

public class JsonBinderAttribute : CustomModelBinderAttribute
{
    public override IModelBinder GetBinder()
    {
        return new JsonModelBinder();
    }
 
    public class JsonModelBinder : IModelBinder
    {
        public object BindModel(
            ControllerContext controllerContext, 
            ModelBindingContext bindingContext)
        {
            try
            {
                var json = controllerContext.HttpContext.Request
                           .Params[bindingContext.ModelName];
 
                if (String.IsNullOrWhitespace(json))
                    return null;
 
                // Swap this out with whichever Json deserializer you prefer.
                return Newtonsoft.Json.JsonConvert
                       .DeserializeObject(json, bindingContext.ModelType);
            }
            catch
            {
                return null;
            }
        }
    }
}

Controller Action

public class PersonController : Controller
{
    // Note: The JsonBinder attribute has been added to the person parameter.
    [HttpPost]
    public ActionResult Update([JsonBinder]Person person)
    {
        // Both the person and its internal pet object have been populated!
        ViewData["PetName"] = person.Pet.Name;
        return View();
    }
}

Sample Models

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    // Note: This property is not a primitive!
    public DomesticAnimal Pet { get; set; }
}
 
public class DomesticAnimal
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Species { get; set; }
}

jQuery Method

function sendToServer() {
    var person = {
        Name : 'Tom',
        Age : 27,
        Pet : {
            Name : 'Taboo',
            Age : 2,
            Species : 'Shiba Inu'
        }
    };
 
    // {"Name":"Tom","Age":27,Pet:{"Name":"Taboo",Age:2,Species:"Shiba Inu"}}
    var personJson = JSON.stringify(person);
 
    $.ajax({
        url: 'Person/Update', 
        type: 'POST',
        data: { 
            person: personJson 
        }
    });
}
Shout it

Enjoy,
Tom

Real Time Web Analytics