Thursday, March 3, 2011

Working with Json in ASP.NET MVC, easily sending objects back and forth between server and client

Working with Json in ASP.NET MVC is a truly easy experience. MVC gives you all the tools you need to move Json objects back and forth between the client and the server, with very few lines of code. In this demo I'll show you how to take a Json string from the client and with 2 lines of code, turn it into a C# object on the server.

First we'll need a new ASP.NET MVC 3 project. We'll add 3 files to this project:

1. We need to create the C# object that we'll convert our Json to. We'll call this class 'CoolJsonObject' and give it a few properties:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace JsonDemo.Models
{
    public class CoolJsonObject
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Message { get; set; }
    }
}


2. We'll need an extremely simple 'Index' page for this example. Nothing more than a hidden field and a submit button. In our hidden field we've added our Json string. As you can see, the properties of the Json object match the properties of the C# object exactly. This is key, they have to match and it is case sensitive. On the post, we'll use the FormCollection to pull this value out by its name.

@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <title>Index</title>
</head>
<body>
    <div>
        @using (Html.BeginForm("PostJson", "JsonDemo")) {
            <input type="hidden" name="MyCoolJson" value="{ 'FirstName':'John', 'LastName':'Wayne', 'Message':'Hey there pilgrim!' }" />
            <input type="submit" value="submit" />
        }
    </div>
</body>
</html>


3. Finally, we'll create a simple Controller called 'JsonDemoController', that serves up our Index page and handles the post event.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using JsonDemo.Models;
 
namespace JsonDemo.Controllers
{
    public class JsonDemoController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
 
        [HttpPost]
        public ActionResult PostJson(FormCollection coll)
        {
            JavaScriptSerializer js = new JavaScriptSerializer();
            CoolJsonObject obj = js.Deserialize<CoolJsonObject>(coll["MyCoolJson"]);
            return RedirectToAction("Index");
        }
    }
}


As you can see, the post method is extremely small and it doesn't take much to deserialize our Json into a C# object. The magic is in these 2 lines:

JavaScriptSerializer js = new JavaScriptSerializer();
            CoolJsonObject obj = js.Deserialize<CoolJsonObject>(coll["MyCoolJson"]);


All we do is create a new instance of the JavaScriptSerializer class. Then we call the Deserialize method on this object, giving it our C# object type and passing it our Json string, which we get out of the FormCollection by its name property. Its that easy!

Debugging you can see our C# object has been populated with the properties from our Json string. Pretty cool!



Now you may ask, what about sending Json back down to the client? I'm glad you asked! Its even easier, with only 1 line of code:

public ActionResult GetSomeJson()
        {
            CoolJsonObject obj = new CoolJsonObject() { FirstName = "John", LastName = "Wayne", Message = "Goodbye pilgrim!" };
            return Json(obj);
        }


As you can see here, just create a new ActionResult method and return Json(). If you called this method from a jQuery ajax call, the 'data' object you get back would be a CoolJsonObject in Json format! You can't beat that.

Enjoy!

4 comments:

  1. Curiously, when I return Json(obj); it asks me if I want to open or save the file. Why is this?

    ReplyDelete
    Replies
    1. @Chris Grimes - It may be an issue with MIME types on your server. If your server is attempting to send the JSON data to the client browser as a file, rather than a data stream, then the browser will be forced to offer download of the file. I'm sorry I'm not able to offer more specific instructions on fixing this, but I hope I helped point you in the right direction.

      Delete
  2. return Json(rpMembers, JsonRequestBehavior.AllowGet);

    ReplyDelete