Skip to main content

JSON, ASP.NET MVC and JQuery - Working with Untyped JSON made easy

image

In this post, we’ll create a JsonValue binder for ASP.NET MVC3, to parse incoming Json to the JsonValue implementation to access/modify values in an untyped way, using ‘dynamic’ features (See the examples below).

Note: ASP.NET MVC3 already supports binding incoming Json to typed parameters, read more about that in Scott’s post. This post is more towards untyped, server side Json manipulation scenarios.

A Quick Preface on JsonValue Implementation

Few months ago, Glenn Block posted about the new WCF web API stack, and in his PDC talks, he demonstrated the new Json primitives with ‘dynamic’ support.

To summarize, this allows you to manipulate Json data using a dynamic wrapper, as shown in Glenn’s post.

[ServiceContract]
  
  //A method in your service
  public JsonValue Post(JsonValue contact)
    {
        var postedContact = (dynamic)contact;
        var contactResponse = (dynamic)new JsonObject();
        contactResponse.Name = postedContact.Name;
        contactResponse.ContactId = nextId++;
        return contactResponse;
    }

From Glenn's post

In the snippet above you can see that the Post method accepts a JsonValue and returns a JsonValue. Within it casts the incoming parameter to dynamic (there actually is an extension method AsDynamic which you can use) pulls out the name and then creates a new JsonObject which it sets some properties on and returns.

I’m a big fan of fluent wrappers on top of data formats like Json and Xml (See my previous ElasticObject implementation). The new JsonValue class comes with a bunch of goodness, Read the documentation here, and have a look at the actual implementation here

 

Creating a JsonValue binder for ASP.NET MVC

Now, Let us see how to create a model binder for MVC, to accept Json data you may post from the client side using JQuery. The idea is to to parse the same to the JsonValue object and hand over the same to a parameter of an Action in your controller. This will enable you to leverage the goodness of JsonValue for untyped scenarios, from your ASP.NET MVC controllers.

At this point, you may fire up your Visual Studio, and start a new ASP.NET MVC3 application. Next, you need to add references to the Microsoft.Runtime.Serialization.Json library. You can do this either by downloading the codebase from http://wcf.codeplex.com, or you can get going easily by adding a package reference to WcfWebApis from your MVC project, using nuget. Just goto View->Other Windows->Package Manager console, and type

install-package WcfWebApis

You may also read more about installing packages via Package Manager Console

Once you’ve the package reference added - You can put together a model binder in your MVC project to parse the incoming Json, to return a JsonValue object as shown. Read more about Modelbinders here if required

So, here is our DynamicJsonBinder which parses the incoming Json data to a JsonValue instance.

  public class DynamicJsonBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {

            if (!controllerContext.HttpContext.Request.ContentType.StartsWith
                ("application/json", StringComparison.OrdinalIgnoreCase))
            {
                // not JSON request
                return null;
            }

            var inpStream = controllerContext.HttpContext.Request.InputStream;
            inpStream.Seek(0, SeekOrigin.Begin);

            StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
            string bodyText = reader.ReadToEnd();
            reader.Close();


            if (String.IsNullOrEmpty(bodyText))
            {
                // no JSON data
                return null;
            }

            return JsonValue.Parse(bodyText);
        }

    }
We'll also need a custom model binder attribute, to tie the above Modelbinder to an action parameter of a given Action in a controller.
    public class DynamicJsonAttribute : CustomModelBinderAttribute
    {
        public override IModelBinder GetBinder()
        {
            return new DynamicJsonBinder();
        }
    }

Once you’ve the Model and ModelBinder ready, add a method/action in any of your MVC project Controllers. We’ll create a simple action that’ll accept a product and will return a list of suppliers, all using JSON.

        public ActionResult GetSuppliers([DynamicJson] JsonValue product)
        {

            var prod = product.AsDynamic();

            //Assume you are getting suppliers from a document database
            //based on prod.name
            var sup = JsonValue.Parse(@"[{""name"":""Supplier1""},
                                    {""name"":""Supplier2""}]");
            prod.suppliers = sup;

            //Return the modified json object
            return Content(product.ToString(), "application/json");
        }

So, I just added a GetSuppliers action to my Home controller, which takes a JsonValue object. Note that we are marking our action parameter with the [DynamicJson] attribute we created above - to ensure that our DynamicJsonBinder is invoked to bind the incoming Json data to the action parameter.

Also, we are manipulating the JsonValue object in our controller (just attaching some suppliers), and returns the same as Json with out any friction. You may note how easily this will go with JSON data sources, like document dbs. JsonValue implementation also supports Linq to Json, see the documentation on JsonValue here in Codeplex.

The Client Side

Ok, now we are ready to post a product to our GetSuppliers method, and get the result. We’ll just make a JQuery ajax post to our HomeController’s GetSuppliers action, with a product, when the user clicks the button btnGetSuppliers.

    <script type="text/javascript">

        $(document).ready(function () {
            var product = { name: "Pizza" };
            $("#btnGetSuppliers").click(function () {
                $("#prods").html("");
                $.ajax({
                    url: "/Home/GetSuppliers",
                    type: "POST",
                    dataType: "json",
                    contentType: 'application/json',
                    data: JSON.stringify(product),
                    success: function (response) {
                        $("#prodtemplate").tmpl(response).appendTo("#prods");
                    }
                });
            });

            $("#prodtemplate").tmpl(product).appendTo("#prods");

        });
    
    </script>

And you may also notice in the above code that, up on success, we are rendering the response using the JQuery Template plugin, to the prods div.

A template contains markup with binding expressions. The template is applied to data objects or arrays, and rendered into the HTML DOM.

In this case, remember that we modified our Json object in our Controller’s action to attach suppliers to it and then returned the Json - So the data that you’ll be getting back from your controller action may contain suppliers. We’ll render the Product using the template below. You may read more on how to use JQuery template’s tmpl() function to render templates here. The related html and the template is given below.

<input type="button" id="btnGetSuppliers" value="Send JQuery" />
<div id="prods" />


 <script id="prodtemplate" type="text/x-jquery-tmpl">
        <div>
           Name: ${name}<br/>
           {{if suppliers}}
           Suppliers:
           <ul>
           {{each(i,supplier) suppliers}}
            <li> ${supplier.name}</li>
           {{/each}}
           </ul> 
           {{/if}}
        </div>
    </script>

So, to conclude – We just saw how easy it is to work with Json data in ASP.NET MVC, especially leveraging the new JsonValue implementation. And this has some very interesting possibilities that I’ll explore later.

You may also read my previous posts on ASP.NET MVC and JQuery if you are interested.

Popular posts from this blog

Creating a quick Todo listing app on Windows using IIS7, Node.js and Mongodb

As I mentioned in my last post, more and more organizations are leaning towards Web Oriented Architecture (WOA) which are highly scalable. If you were exploring cool, scalable options to build highly performing web applications, you know what Node.js is for.After following the recent post from Scott Hanselman, I was up and running quickly with Node.js. In this post, I’ll explain step by step how I’ve setup Node.js and Mongodb to create a simple Todo listing application.Setting up Node.jsThis is what I’ve done.1 – Goto http://nodejs.org/, scroll down and download node.exe for Windows, and place it in your c:\node folder2 – Goto IIS Node project in Git at https://github.com/tjanczuk/iisnode, download the correct ‘retail’ link of IIS Node zip file (I downloaded the already built retail package, otherwise you can download and build from the source).3 – Extract the zip file some where, and run the install.bat or install_iisexpress.bat depending on your IIS Version. If you don’t have IIS in…

Top 7 Coding Standards & Guideline Documents For C#/.NET Developers

Some time back, I collated a list of 7 Must Read, Free EBooks for .NET Developers, and a lot of people found it useful. So, I thought about putting together a list of Coding Standard guidelines/checklists for .NET /C# developers as well.As you may already know, it is easy to come up with a document - the key is in implementing these standards in your organization, through methods like internal trainings, Peer Reviews, Check in policies, Automated code review tools etc. You can have a look at FxCop and/or StyleCop for automating the review process to some extent, and can customize the rules based on your requirements.Anyway, here is a list of some good Coding Standard Documents. They are useful not just from a review perspective - going through these documents can definitely help you and me to iron out few hidden glitches we might have in the programming portion of our brain. So, here we go, the listing is not in any specific order.1 – IDesign C# Coding StandardsIDesign C# coding stand…

MVVM - Binding Multiple Radio Buttons To a single Enum Property in WPF

I had a property in my View Model, of an Enum type, and wanted to bind multiple radio buttons to this.

Firstly, I wrote a simple Enum to Bool converter, like this.

public class EnumToBoolConverter : IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (parameter.Equals(value)) return true; else return false; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return parameter; } #endregion }

And my enumeration is like

public enum CompanyTypes { Type1Comp, Type2Comp, Type3Comp } Now, in my XAML, I provided the enumeration as the ConverterParameter, of the Converter we wrote earlier, like
<Wi…