I tried jQuery for the first time a couple of weeks ago, and got blown away by the power this library adds to the Java Script language. I finally found a library that can do the heavy lifting for me when developing web application the Web 2.0 way.
The more I played with this library, the more addicted I got. And I could easily imagine this library in use with existing web applications frameworks such as the new and upcoming ASP.NET MVC. And this actually became my first development task with jQuery. A task where I used the Ajax functionality to communicate with the ASP.NET MVC framework on the server side - something several people already have done before me (Fredrik Karlseth). Scott Hanselman also stated that he would like to see some jQuery love from the community.
After a few hours programming jQuery, I decided that I would try to develop some jQuery plugins to speed up the Ajax programming against ASP.NET MVC. And this decision is the main reason for this post.
Also let me emphasize that there is no lack of Ajax support in the ASP.NET MC framework. In the Preview 4 (or was it 3, I’m not sure) release of ASP.NET MVC, they shipped built-in Ajax functionality for forms and ActionLink – which is a good start! But their Java Scripts is not based on jQuery and the functionality is basic. Before I start on the jQuery plugins, let’s have a look at the built-in Ajax support.
The built in Ajax support will let you create Ajax Forms and ActionLinks. The Java Script code is located inside two libraries in the Content directory.
They have also added a View helper called Ajax that generates HTML that is wired up to these two Java Script libraries.
For instance the ActionLink will create an A tag and add an event handler to the onClick event. Notice the specification of the UpdateTargetId; this is the ID of the object where the response from the Ajax request will be rendered. This is good for those partial rendering scenarios. It’s also possible to define which Java Script function to call before and after (OnBegin and OnSuccess) the Ajax request. Something that’s useful when you want to display a progress bar while the Ajax request is being processed.
On the server side you also have functionality to detect if the request made from the client (web browser) is an Ajax call.
If you want more details, read Hanselmans post.
One of the first things that I did was to mimic the built-in Ajax functionality in ASP.NET MVC. I decided to drop using a View Helper to generate HTML and wiring up the Ajax functionality, and rater use plain old Java Script and jQuery to Ajax enable Forms and Links (ActionLinks). When deciding this I had in mind that the ASP.NET MVC framework is designed for extensibility and one of the extensibility points is the View engine. I wanted the Ajax functionality to be agnostic of this, so the functionality can be used across several View engines. It goes like this:
You might notice that I extended the jQuery library with new functions (ajaxActionLink and ajaxForm). These are so called plugins, which is the extension point of jQuery. It’s also possible to specify which object to update when Ajax response is received from the server, just like the built-in Ajax library.
Also notice that both the ActionLink and the Form sample had the HTML generated by the server (View), and that I only used Java Script and the jQuery plugins to configure and enable the Ajax functionality. The plugins extracts the information they need out from the HTML generated by the server, and use this information to enable the Ajax functionality. Typical information is the href attribute from the link (ActionLink) object, and the action and method attributes and input objects in the Form. The HTML generated by the View is illustrated on the picture below.
Just mimicking existing functionality in an existing framework isn’t that much fun, so I also added some new features as well. One of the cool features in jQuery is that you easily can select objects from the DOM based on an expression (like the SELECT statement in LINQ and SQL). For instance, you can select all the links inside a DIV, and then start to manipulate the functionality of these. Let’s say we have a DIV container with several links, like in the sample below:
And we want to Ajax enable both of these links, it goes like this:
Notice the expression inside the jQuery call, which states: find the object where id=actionsLinks and select all links objects within. The ajaxActionLink plugin will recognize that this is a list of link objects, and it will Ajax enable all of them.
But it didn’t stop here. I also added support for an AjaxDropDownList. The idea is the same as with the Form and ActionLink features. You select an existing drop down list object (select) from the DOM and configure it for Ajax. The drop down list must be generated by the server (View), and the only thing you need to do is to configure the URL to request when the user selects an element in the dropdown. When the selection is changed, it will trigger an Ajax call to the server. It goes like this:
Remember that these plugins require the HTML to be generated by the server (Views). For instance, you have to render the whole form (action, inputs etc.) and link (URL) on the server, before Ajax enable them, and when they reach the client (browser) you can configure the Ajax functionality using these jQuery plugins.
All of these plugins also have the same callback functions for onBegin and onSuccess like the built-in Ajax functionality. Jo will see this configuration in the examples below.
One of the great inventions in ASP.NET MVC, is the Routing mechanism, which was invented by TheGu himself. Explained with one sentence; this gives you 100% control of the URLs in your web application and enable you to configure how the URL should be mapped to the logic (Controller) in your app. With the standard HTML View helpers you can generate links like this:
Notice that the URL isn’t defined at all, the only thing you input is the name of the Controller and the Action, and then the View Helper extracts information from the Routing mechanism and generate a URL based on the information. Smart? - Very! And it’s very DRY (Don’t Repeat Yourself). You don’t repeat yourself and you don’t hard code the URL into a View. You just point out which controller and what Action to be called.
The jQuery plugins mentioned above requires that the server (Views) generate the HTML, and then they extract out the information when they add Ajax functionality to the HTML output. What if we could skip this part, and let the jQuery plugins do all of the Ajax and lifting for us? Like the View helpers does on the server side. Wouldn’t that be nice? Of course it would and it goes like this:
Notice that I now specify the name of the Controller and Action client side. –Hold on, the client side doesn’t know about theGus routing mechanism, so how can they generate a valid URL for me?
It’s not black magic; I’ve implemented a Controller for the jQuery plugins that lives on the server side. This Controller gives the jQuery plugins information about the other Controllers, their actions and routes, and other metadata. Based on this data the jQuery plugins can generate a valid URL based on the routes configured for the application.
Also notice that in the scaffolding example above, I’ve only generated an empty tag with an id attribute on the server, and the jQuery plugin will generate rest of the information.
The scaffoldDropDownList plugin will ask the server for data and use it to populate the dropdown with content. This is done by specifying which action on the server to be called, by setting the name of the action in the listAction parameter. The plugin expect the server to return JSON.
I’ve also started on a Scaffolding plugin for forms, where I can practically use the metadata from the JQuery controller to generate a form. This functionality is not done yet. I’m also planning to support templates for this scaffolding mechanism. I’m at a point in the development where I hope I can get some help from the community. This is a good start, but far away from done, it’s just a Proof of Concept to show off jQuery together with the ASP.NET MVC framework.
YES! I’ve attached the source code as a zip file. This code is free to use as you like. I also hope I can get some help from you on further development on these plugins. Also, let me emphasize that this is only a proof of concept, and it has a certain road to walk before I even can call it Beta. I’ve created a project on Codeplex, but I haven’t had time to move the source code over there. After I’m home from vacation I will move the source code.
Download the source here
Remember Me