Friday, March 4, 2011

ASP.NET MVC: How to emit dynamically generated Javascript

Using ASP.NET WebForms, it is common to use the ClientScriptManager to act as a bridge between the page and the server for carrying out operations relating to Javascript.  A common example is to register an object graph as a Javascript array on the client:
var serializer = new JavaScriptSerializer();
var js = string.Format(
    "var arr = {0};",
    serializer.Serialize(foo));

var cs = Page.ClientScript;

if(!cs.IsClientScriptBlockRegistered(this.GetType(), "arr"))
{
    var sb = new StringBuilder();
    sb.Append(@"");
    cs.RegisterClientScriptBlock(this.GetType(), "arr", sb.ToString(), false);
}

In the ASP.NET MVC world, we approach this task somewhat differently.   Using the resource-based model of MVC, we can get a cleaner implementation without having to use the ScriptManager to act as a middle-man.

What we want to end up with is to have our Javascript be requested just as any other static resource in our page would be.  So we can start by modeling that approach with a script tag pointing to a url:
<script src="@Url.Content("~/app/scripts/usertags")" type="text/javascript"></script>
Next, we must create a controller and an action that will serve up the dynamic Javascript content.
public class ScriptsController : Controller
{
    public JavaScriptResult UserTags()
    {
        var accountId = ((AppIdentity)this.User.Identity).Id;
        var s = "alert(\"Account: " + accountId + "\");";
        return JavaScript(s);
    }
}
Using this approach we can group all of our dynamically generated scripts together and therefore manage and test them accordingly without having the whole page framework getting in the way.  In the above example you can see that I read a property off of my custom application identity and return it as some Javascript.

If you compare what's happening between the MVC approach and the previous approach, you can see that the code very similar.

The final thing to do would be to map a route so that the request gets mapped to the correct controller action.

1 comment:

  1. Your blog has given me that thing which I never expect to get from all over the websites. Nice post guys!

    regards,



    Melbourne Web Designer

    ReplyDelete