Wednesday, February 15, 2012

Passing variables from your Controller to your JavaScript in ASP.NET MVC

GitHub link to NGon: https://github.com/brooklynDev/NGon

Last night I was watching the latest RailCast screen cast, where Ryan showed a cool technique in Ruby on Rails on how to pass data from your Controller straight to your JavaScript:

http://railscasts.com/episodes/324-passing-data-to-javascript

Essentially, it involved using a gem called Gon which enabled you to do this in your controller:



I thought that was pretty cool, and it'd be awesome to have the same thing in ASP.NET MVC. Enter NGon. The code is actually very simple, but I think the usage is quite elegant (It's up on GitHub here, complete with Unit Tests and a sample app).

Usage:


The first step is to register the NGonActionFilterAttribute in the global filters in your Global.asax.cs page:



Then, in your Controller, you do this:



Next, in your HTML page (probably in your Layout.cshtml page so it's available everywhere) you add this line:


@Html.IncludeNGon()


At this point, you'll now have access to the values in your javascript:



The cool thing is that it works on more than just simple types. It works on any object which in turn gets serialized into JSON (using the JavascriptSerializer). This allows you to do something like this:



and in your javascript:



Under the hood:



It's actually all quite simple. The first thing that happpens, is when an action gets called, the NGonActionFilterAttribute fires, and it creates a new ExpandoObject called NGon on the Controllers ViewBag property:



Then, as you keep adding items to the ViewBag.NGon property, you're adding it to this underlying ExpandoObject. Finally, when you call the IncludeNGon in the HTML, this is where all the magic happens:



What it does is, it first creates an empty javascript object on the window object. Then, for each property in the ViewBag.NGon property, it adds the serialized version of it to that javascript object on the window object. What you end up with, is something like this:



Cool huh? Drop me a comment, let me know what you think!

5 comments:

Norbert said...

Brilliant! This should get NuGet packaged.

misu said...

Excellent work.

A.Friedman said...

Updated to use JSON.Net, and added this to NuGet: https://nuget.org/packages/NGon.

Matthew Nichols said...

It is a really great (and focused) library. I use it a lot and recommend it to others. Thanks for sharing it.

One question; when I am setting up a controller that uses NGon in my test fixtures I have been doing a line like this:

_controller.ViewBag.NGon = new ExpandoObject();

since the global filter doesn't get fired. Is that what you do?
-Matthew

A.Friedman said...

@Matthew: Yea, that's exactly what I do in my tests as well. I know it isn't perfect, and there ARE ways to mock/stub action filters, but in this particular case I just don't think it's worth it.