Posting JSON Data to ASP.NET MVC Posting JSON Data to ASP.NET MVC ajax ajax

Posting JSON Data to ASP.NET MVC


Take a look at Phil Haack's post on model binding JSON data. The problem is that the default model binder doesn't serialize JSON properly. You need some sort of ValueProvider OR you could write a custom model binder:

using System.IO;using System.Web.Script.Serialization;public class JsonModelBinder : DefaultModelBinder {        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {            if(!IsJSONRequest(controllerContext)) {                return base.BindModel(controllerContext, bindingContext);            }            // Get the JSON data that's been posted            var request = controllerContext.HttpContext.Request;            //in some setups there is something that already reads the input stream if content type = 'application/json', so seek to the begining            request.InputStream.Seek(0, SeekOrigin.Begin);            var jsonStringData = new StreamReader(request.InputStream).ReadToEnd();            // Use the built-in serializer to do the work for us            return new JavaScriptSerializer()                .Deserialize(jsonStringData, bindingContext.ModelMetadata.ModelType);            // -- REQUIRES .NET4            // If you want to use the .NET4 version of this, change the target framework and uncomment the line below            // and comment out the above return statement            //return new JavaScriptSerializer().Deserialize(jsonStringData, bindingContext.ModelMetadata.ModelType);        }        private static bool IsJSONRequest(ControllerContext controllerContext) {            var contentType = controllerContext.HttpContext.Request.ContentType;            return contentType.Contains("application/json");        }    }public static class JavaScriptSerializerExt {        public static object Deserialize(this JavaScriptSerializer serializer, string input, Type objType) {            var deserializerMethod = serializer.GetType().GetMethod("Deserialize", BindingFlags.NonPublic | BindingFlags.Static);            // internal static method to do the work for us            //Deserialize(this, input, null, this.RecursionLimit);            return deserializerMethod.Invoke(serializer,                new object[] { serializer, input, objType, serializer.RecursionLimit });        }    }

And tell MVC to use it in your Global.asax file:

ModelBinders.Binders.DefaultBinder = new JsonModelBinder();

Also, this code makes use of the content type = 'application/json' so make sure you set that in jquery like so:

$.ajax({    dataType: "json",    contentType: "application/json",                type: 'POST',    url: '/Controller/Action',    data: { 'items': JSON.stringify(lineItems), 'id': documentId }});


The simplest way of doing this

I urge you to read this blog post that directly addresses your problem.

Using custom model binders isn't really wise as Phil Haack pointed out (his blog post is linked in the upper blog post as well).

Basically you have three options:

  1. Write a JsonValueProviderFactory and use a client side library like json2.js to communicate wit JSON directly.

  2. Write a JQueryValueProviderFactory that understands the jQuery JSON object transformation that happens in $.ajax or

  3. Use the very simple and quick jQuery plugin outlined in the blog post, that prepares any JSON object (even arrays that will be bound to IList<T> and dates that will correctly parse on the server side as DateTime instances) that will be understood by Asp.net MVC default model binder.

Of all three, the last one is the simplest and doesn't interfere with Asp.net MVC inner workings thus lowering possible bug surface. Using this technique outlined in the blog post will correctly data bind your strong type action parameters and validate them as well. So it is basically a win win situation.


In MVC3 they've added this.

But whats even more nice is that since MVC source code is open you can grab the ValueProvider and use it yourself in your own code (if youre not on MVC3 yet).

You will end up with something like this

ValueProviderFactories.Factories.Add(new JsonValueProviderFactory())