Geeks With Blogs
Pounding Code technological rantings and code samples

 

I had started to write this post a while back, but never polished it up enough to make it worthy of print, however it does offer some insight into a clean way of injecting model variables into javaScript the 'right way'*, that is not putting <%= %> tags in your script. I've learned quite a lot since I started this blog posting, so I'm NOT recommending this as the only approach, or best approach, etc. Just as a neater way to inject your model into your client side script.

An example of using JQuery with ASP.NET/MVC with Rick Stahl''s Web Utility to populate child controls:

 Let's assume you want to use JQuery where you wish to have client side data sent back to a controller without a full page post back.

 * I did say 'reight way' in quotes - ;-)

For the project:

You need to inject a client-side JavaScript. While you can spin one up by hand, why not use go green and recycle?  Rich Stahl's site: http://www.west-wind.com has a variety of tools, some of which are free. Download http://www.west-wind.com/westwindwebtoolkit/. What we're interested in here is the Web Utility Support Classes

 Download the utility and add references for Westwind.Utilities and Westwind.Web to your project. You'll also need to add ScriptVariableInjectionHelper.cs to your helpers folder.

 ScriptVariableInjectionHelper provides an easy way for server code to publish strings into client script code. This object basically provides a mechanism for adding key value pairs and embedding  those values into an object that is hosted on the client.

 

For the Master Page:

Before you start injecting scripts willy-nilly all over your pages, it is better to inject all of your client-side scripts into the header along with your other JavaScript includes.. If you are using a master page, this becomes very easy. Beneath where you put all of your other site-wide include tags, and above a content placeholder for page-level scripts, I also add a simple test for controller scripts I inject into the ViewData and a test to verify it is there before you write it out.

 

<script type="text/javascript" language="javascript" src="<%=Url.Content("~/Content/Scripts/jquery-1.3.2.min.js")%>"></script>

  <% if(ViewData.Contains("clientScript")){

        Response.Write(ViewData["clientScript"].ToString());

  }%>

<asp:ContentPlaceHolder ID="Scripts"   runat="server" />

</head>

 

For the Controller:

Now that we have a way to inject our script and a target to inject it into, we need to simply send it down for manipulation.

 

From your ActionMethod we add a call to a new InjectClientScript method...

public virtual ActionResult Edit(Guid id)

  {

      Criterion model = _CriterionSvc.GetCriterion(id);

      InjectClientScript(model);

      return View(model);

}

 

private void InjectClientScript(object model)

{

    // instantiate the utility (view is the name of the JavaScript object that will appear in the View

    ScriptVariables scriptVars = new ScriptVariables("view");

    // add our ProfileCommon data (user context)

    scriptVars.Add("Profile", profile.Preferences);

    // add our model being injected

    if (model != null)

      scriptVars.Add("Model", model);

    // call the westwind utility and inject into viewdata

    ViewData["clientScript"] = scriptVars.GetClientScript(true);

 }

 

For the view:

The output is injected into a variable called view, which in turn contains our Controller objects we injected (Profile and Model). Note Model contains objects of its own. In this example, CriterionType is one such object. You can configure the westwind utility to traverse child objects or not.

 
<script type="text/javascript"> 
var view = {
 Profile: {"CountryId":0,"StateId":21,"DistrictId":6108},
 Model: {"CriterionTypeId":7,"CriterionType":{"DomainId":1,"Domain":null,"Description":null,"Code":"Instructional Design Skills","Id":7,"Guid":{"Length":36},"ModifiedDate":new Date(-62135578800000),"ModifiedBy":null},"Description":null,"Code":"Teacher provides relevant examples and demonstrations to illustrate concepts and skills.\r\n","Id":31,"Guid":{"Length":36},"ModifiedDate":new Date(1245546360000),"ModifiedBy":"Admin"}
};
</script>

 

You now simply need to access your javascript variables.Below is a simple example of accessing those variables and sending them to a jquery function that would populate a dropdown via ajax.

 

$.PopulateDropdown("CriterionTypeId", "/CriterionType/GetCriterionTypeCollection/" + view.Model.CriterionType.DomainId, view.Model.CriterionTypeId);


 

your jquery plug in would look something like this:

 

(function () {
    $.issPopulateDropdown = function (control, query, selected, emptyMsg) {
        control = "#" + control;
        $(control + ' > option').remove(); // remove any existing options
        $(control).show();
        $('#emptyMsg').remove(); // remove any existing message
        $.ajax({
            type: "GET",
            contentType: "application/json; charset=utf-8",
            url: query,
            dataType: "json",
            success: function (data) {
                if (data.length > 0) {
                    var options = '<option id="0">Select</option>';
                    for (p in data) {
                        var item = data[p];
                        options += "<option value='" + item.Id + "'>" + item.Key + "</option>";
                    }
                    $(control).html(options);
                    $(control).val(selected);
                    $('#emptyMsg').remove();
                }
                else {
                    alert('there are not any existing options');
                    $(control).after('<div id="emptyMsg">' + emptyMsg + '</div>');
                    $(control).hide();
                }
            } // end success          
        });  // end ajax
    } // end issPopulateDropdown

));

Posted on Wednesday, August 25, 2010 8:10 AM MVC , Javascript | Back to top


Comments on this post: injecting model variables into javaScript the 'right way',

# re: injecting model variables into javaScript the 'right way',
Requesting Gravatar...
This is very similar to what I do in my own apps. A few comments:

I was inspired to clean up my javascript includes when I saw MvcContrib's helpers. I even made my own with configurable options so I could change the source paths.

<% Html.ScriptInclude("jquery-1.3.2.min.js") %>
<% Html.Stylesheet("Site.css") %>

In app start you can configure these to wherever:

IncludesHelpers.ScriptLocation = "~/Scripts";
IncludesHelpers.StylesheetLocation = "~/Content/css";

And you can still put a custom path in the helper (override default) if you prefix it with "http://" or "~".


Also, for your InjectClientScript() method I would move that to a global action filter and check if the model inherits from some marker interface like IRequireScriptInjection. Then you'll have a nice AOP/SRP of concerns.
Left by Ryan on Aug 26, 2010 1:21 AM

# re: injecting model variables into javaScript the 'right way',
Requesting Gravatar...
Excellent suggestions! I've been noodling with Telerik's free MVC controls, and they've got a tool which will combined all of your css & js into one file respectively to handle that for you. Check it out
Left by James Fleming on Aug 26, 2010 6:27 AM

Your comment:
 (will show your gravatar)


Copyright © James Fleming | Powered by: GeeksWithBlogs.net