ASP.NET MVC2 Reading JSON data with controller ASP.NET MVC2 Reading JSON data with controller json json

ASP.NET MVC2 Reading JSON data with controller


Right now, you're sending the JSON string as the entire body of your POST. MVC has no way to connect the dots and understand that you wanted it to provide that entire string as a parameter named myString.

To do that, change your client-side data parameter like this:

$.ajax({  url: '/Home/Request',  type: 'POST',  dataType: 'json',  data: { myString: jsonData },  contentType: 'application/json; charset=utf-8',  success: function (x) {    // If ParseResult is some sort of JSON deserializing, don't do that.    // When the dataType is set to 'json', jQuery handles this for you     //  automatically before the success handler is called.    self.ParseResult(x);  }});

When you provide jQuery an object as its data parameter, it automatically URLEncodes that before sending, so something like this will be POSTed to the server:

myString={json:data, here:etc}

MVC will pick that up as the myString parameter as desired then, and you can proceed with deserializing it with JavaScriptSerializer.

Also, unless you're doing something more complicated on the client-side than you're showing, the JavaScript class is unnecessary. Something like this would work:

var testData2 = {  MyInt: 5678,  MyString: "GHIjkl",}var testData1 = {  MyInt: 1234,  MyString: "abcDEF",  Subs: [ testData2 ]}

All that said, why are you using JSON for the request? If you accept a parameter of the custom type in your action, MVC's model binder is pretty good at hydrating that type from standard URLEncoded input data:

public JsonResult Data(MyClass request){  // request.MyInt, request.MyString, etc should exist here.  var answer = ...  // It's okay to accept URLEncoded input parameters, but still return JSON.  return Json(answer, JsonRequestBehavior.DenyGet);}

Then, calling it doesn't require the client-side JSON serialization:

var testData2 = {  MyInt: 5678,  MyString: "GHIjkl",}var testData1 = {  MyInt: 1234,  MyString: "abcDEF",  Subs: [ testData2 ]}$.ajax({  url: '/Home/Request',  type: 'POST',  traditional: true,  dataType: 'json',  data: testData1  success: function (x) {    self.ParseResult(x);  }});

It's a bit simpler all around, and is faster since you've removed a layer of serialization on the client-side and deserialization on the server-side.


In my experience I have to pass in the json as a string and then deserialize it. I use Newtonsoft to do this.

public ActionResult DoAjax(string jsonRequest){    JsonSerializer serializer = new JsonSerializer();    StringReader sr = new StringReader(jsonRequest);    Newtonsoft.Json.JsonTextReader reader = new JsonTextReader(sr);    MyClass obj = (MyClass)serializer.Deserialize(reader, typeof(MyClass));    //...do other stuff}


on a similar tack to josh's, you can use a json actionfilter a la:

// requires newtonsoft.json.dll public class JsonFilter : ActionFilterAttribute{    public string Param { get; set; }    public Type JsonDataType { get; set; }    public override void OnActionExecuting(ActionExecutingContext filterContext)    {        if (filterContext.HttpContext            .Request.ContentType.Contains("application/json"))        {            string inputContent;            using (var sr = new StreamReader(filterContext.HttpContext                                .Request.InputStream))            {                inputContent = sr.ReadToEnd();            }            var result = JsonConvert.DeserializeObject(inputContent, JsonDataType);            filterContext.ActionParameters[Param] = result;        }        else            try            {                // we should do a loop looking for json here ONLY if there's a callback                // i.e. we're calling jsonP                if (filterContext.HttpContext.Request.QueryString["callback"] != null)                {                    string inputContent =                         Enumerable.Where(filterContext.HttpContext                                        .Request.QueryString.Keys.Cast<string>()                                        .Select(qs => filterContext.HttpContext                                        .Request.QueryString[qs]), query => !string.IsNullOrEmpty(query))                                        .FirstOrDefault(query => query.IndexOf("{") == 0);                    var result = JsonConvert.DeserializeObject(inputContent, JsonDataType);                    filterContext.ActionParameters[Param] = result;                }            }            catch (Exception e)            {                // do nothing                filterContext.ActionParameters[Param] = null;            }    }}

usage (in this case typeof(IList)) but can be ANY class ie typeof(myClass):

[JsonFilter(Param = "jsonData", JsonDataType = typeof(IList<FundPropertyWeekSplit>))]public virtual ActionResult AddFundPropertyWeekSplit(IList<FundPropertyWeekSplit> jsonData){    // code to deal with the newly created strongly typed object}

i use this (rather too much!!) all over the shop...