views:

693

answers:

4

Do I have to do anything special to my controller action method to accept/bind data from a .ajax() call?

Controller Action -

public class TestController : Controller
{
    public JsonResult GetTestJsonData(Metadata data)
    {
        return new JsonResult { Data = data };
    }
}

JQuery Call -

<script type="text/javascript">
    $(document).ready(function() {
     $.ajax({
      type: "POST",
      url: "GetTestJsonData",
      data: "{ data: {Name:'joe'}}",
      contentType: "application/json; charset=utf-8",
      dataType: "json",
      success: function(msg) {
       alert("Name = " + msg.Name);
      }
     });
    });
</script>

I would expect that this page would alert with the name 'joe'. I'm passing json data from the client to the controller action and the action passes it back to the client. This is just a simple example of what I'm trying to do.

+2  A: 

Your code will probably work for a simple example as you are not parsing anything, however if you wanted to translate your JSON to a real object on the controller action then you will need to tell MVC how to go about it.

There is a blog post on writing a JsonFilterAttribute which uses Json.NET to de-serialize the incoming JSON and translate it into an object.

http://blogger.forgottenskies.com/?p=252

argibson
thats what I was looking for, thanks.
chief7
A: 

Write a custom ModelBinder that understands JSON. You can use a JSON library to deserialize this into your object, then return it.

Then your action becomes:

public ActionResult GetTestJsonData([JsonBinder] Metadata data)
{
   return Json(data);
}
Ben Scheirman
+2  A: 

The other answers require a custom binder, but if that's outside the scope of your application, there's another way. There is no need to deserialize for POSTs if your JSON properties match parameters on your ActionResult method (i.e. it's not a complex JSON object).

<script type="text/javascript">
    $(document).ready(function() {
        $.ajax({
                type: "POST",
                url: "GetTestJsonData",
                data: "{ name:'joe', id:1, age:18 }",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function(msg) {
                        alert("Name = " + msg.Name);
                }
        });
    });
</script>

Which can be consumed by the following ActionResult:

public ActionResult GetTestJsonData(string name, int id, int age)
{
  Metadata data = new Metadata(name, id, age);

  return Json(data);
}
Peter J
not really the answer I was looking for but great info to have, thanks.
chief7
A: 

I've been using the JavaScriptSerializer class in the System.Web.Script.Serialization namespace to do this with great success and it couldn't be simpler. The key is that your javascript json object that you pass up to your controller method needs to have the same structure as the .NET object you're trying to serialize it to. For instance, let's say this is the target .NET object in your controller.

class TestObject {
    public string Name {get;set;}
    public int Age {get;set;}
}

Then your JavaScript object would look like this...

{Name: 'Lunchy', Age: 28}

Then in your controller which would look something like this, (assuming you stringify your javascript object before you pass it to your controller. I use the JSON.stringify(jsObj) method).

public JsonResult TestSerialization(string jsonString)
{
    var jss = new JavaScriptSerializer();
    TestObject to = jss.Deserialize<TestObject>(jsonString);

    return Json(TestObject);
}

This is untested code, and I'm especially unsure of my json object syntax, but hopefully you get the idea. Also note, MSDN may show the JavaScriptSerializer class has been marked as deprecated, but this has been retracted. It's actually the class that the MVC framework uses to do its json serialization.

Lunchy