I decided to spend this weekend digging into the Framework and seeing how I could leverage JQuery features to create a better user experience. One of the more notable things I have come across to this point is the use of the JQuery Load function in place of User Control string generation.
One of my favorite techniques for loading Server driven content via JavaScript is to create an ASCX with the appropriate HTML template and then load its HTML via JavaScript from a web service based request. JQuery makes it very easy to append the HTML you get back and you can really encapsulate a lot of the heavy lifting inside the user control.
There really is no problem with this approach and I will still continue to use it for many things, however, with the routing mechanism that MVC offers you can greatly simplify the process by which this dynamic content is generated and gain greater flexibility for generating it. Let me explain:
I wont give a long overview of how routing works, if your interested, I invite you to read this blog post by Scott Guthrie for more information. Needless to say, I have a very basic routing setup with the following rule:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = 0 }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
If we wanted to use the Action Link ‘/Test/EditSeries/14’ to follow this route, we can expect to create a method EditSeries in our TestController which takes a single parameter for the ‘id’. The method would then designate which view to use once the controller method completes its execution.
As for applying this to the Load method provided by JQuery, we have to simply understand that Load will make an HTTP request which will invoke the routing. Here is the JavaScript I am currently using:
$("#addGenre").click(function() { $("#genreContainer").append(""); $("#genreContainer").append("
"); $("#genreContainer > .genreSelect:last").load("/Test/GenreSelect", null, function() { // setup the new slider SetupSlider($(this).find(".slider"), 0); SetupCloseIcon($(this).find(".removeGenre")); $(this).css("display", "block"); }); });
You will notice that I am passing a valid MVC routing path to Load, this will cause the routing to invoke the GenreSelect method of the TestController class. I also defined GenreSelect.ascx in the same location as the View whose JavaScript is calling this “user control view”. Thus my controller code for this operation looks like such:
public ActionResult GenreSelect() { ViewData["Genres"] = Genres.GetAllGenres(Context); return View("Series/GenreSelect"); }
Notice how simple this code is, and this is all that needs to be done to prepare the “partial” view.
The basic premise of this posting is to show how you can leverage some of the automated content loading features of JQuery and the MVC routing system to simplify this sort of an operation. It also makes more sense given the premise of what we are doing.
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Your using hard coded routes in your example..e.g >>$(“#genreContainer > .genreSelect:last”).load(“/Test/GenreSelect”, null,….>>This will break severely if you ever change your routing definition (for example adding “.mvc” to the controllers to make your site work with IIS 6). You will need to manually update all of your links in your code which is definately <>NOT Dry<>. You should be using the Html.Actionlink helper, however this leaves you with a dilemma when coding javascript, as now your javascript code will need to be interpreted by a view engine, and can’t simply be served from the /Scripts folder. It will be interesting to see how the MS Dev team address these kinds of dilemma’s.
LikeLike
I would suggest using UFrame, which is like UpdatePanel for ASP.NET MVC:>>http://www.codeplex.com/uframe>>This uses jQuery or MS AJAX, whatever framework you have. It works in regular ASP.NET project, as well as, ASP.NET MVC project.
LikeLike
When all else is lost the future still remains.
————–
Georg-August-University Goettingen
LikeLike
Very nicce!
LikeLike
Wow this is a great resource.. I’m enjoying it.. good article
LikeLike
really great post. I'm new to MVC i'm going to try and push post code via Jquery I love how MVC intergrates so well.
LikeLike