Introduction
Have an ASP.NET 1.1 site that you want to quickly add some AJAX functionality to? Could you use the new Microsoft AJAX release? Of course, but you could also use any of the popular JavaScript libraries available and do it yourself just as easily. In some cases, you may not want to use the new Microsoft AJAX. Luckily, there are plenty of other good (and easy) alternatives! This article will demonstrate how to use a popular JavaScript library (jQuery) to add AJAX capabilities to your application with a minimal amount of code.
Background
So, why wouldn't you upgrade to ASP.NET 2.0 and just use the new AJAX functionality provided by Microsoft? Well, if your site is deployed and working – you may not want (or be able to) upgrade to ASP.NET 2.0 as quickly as you would like to. You could, of course, use the new Microsoft AJAX functionality in your ASP.NET 1.1 application (as noted in this article), but just in case you don't want to – this article offers another alternative. Most of the popular JavaScript libraries available today have AJAX functionality built right in, and it's usually a snap to use. Some of the most popular JavaScript libraries are Prototype, Yahoo User Interface Library (YUI), and jQuery. jQuery happens to be my personal favorite, so that's what this sample will use. I could wax poetic on why I like it so much, but as that isn't the point of this article, I'll let you decide for yourself. Whichever one you choose, the process outlined in this article shouldn't vary all that much. With all of that out of the way, let's get started.
This sample will utilize a popular JavaScript library called jQuery to provide almost everything we need to utilize AJAX in this sample. If you are unfamiliar with jQuery, it is an extremely lightweight JavaScript library that has changed the way that I write JavaScript. It's made the process a lot more enjoyable as well.
Using the code
The attached demo project includes both samples described here. To use it, unzip it to a directory on your system, and then create a Virtual Directory in IIS called "AJAXJQuerySample", and point it to the folder that contains the unzipped files. Next, just open the AJAXJQuerySample.csproj file!
Pre-requisites
First, you'll need to download the latest version of the jQuery JavaScript library from here (version 1.1 at the time of this writing). While you're doing this, you might want to bookmark the jQuery site for a quick browsing later on. One of the reasons that this is my library of choice is because of the extremely active user base. The forums are very active, and questions are usually answered very quickly. There are also tons of "plug-ins" that other users have made for jQuery that do just about anything you can think of.
Sample 1: Get the current date and time from the server
For this first example, we'll be creating a simple page that grabs the current time from the server. To begin, we'll need to include the jQuery file in our "Default.aspx" page, like so:
<script type="text/javascript" src="jquery-1.1.js">
Then, we'll use jQuery to setup the AJAX action that we want to happen when the user clicks on the "Get Server Time" link:
$(function() {
//this code is executed when the page's onload event fires
$("a#runSample1").click(function() {
$.get("GetServerTime.aspx", function(response) {
alert(response);
});
});
});
In case you're wondering what you're looking at, let's go over it line by line. The first line is executed when the page's "onload
" event is fired:
$(function() {
Then, we look for the "a
" tag with an ID
of "runSample1
", and then bind to the "onclick
" event:
$("a#runSample1").click(function() {
Now that we're bound to the link's "onclick
" event, we can write the code that we want to execute when it is clicked. The following line is executed when the link's "onclick
" event is fired. This line makes a call to the "GetServerTime.aspx" page (we'll create that shortly), and returns the output of that page into the "response
" variable. Then, we display the response in an alert box.
$.get("GetServerTime.aspx", function(response) {
alert(response);
});
Now, let's take a look at the "GetServerTime.aspx" page. For this page, we don't want any HTML to be output, so we'll remove all of the HTML and just leave the reference to the code-behind file.
<%@ Page language="c#" Codebehind="GetServerTime.aspx.cs"
AutoEventWireup="false" Inherits="AJAXJQuerySample.GetServerTime" %>
(**Note: You could also point to an HttpHandler, but in the interest of brevity, this example will follow this method.) The code-behind file should have the following code:
private void Page_Load(object sender, System.EventArgs e)
{
Response.Expires = -1;
//required to keep the page from being cached on the client's browser
Response.ContentType = "text/plain";
Response.Write(DateTime.Now.ToString());
Response.End();
}
The first thing we need to do is keep the page from being cached in the browser:
Response.Expires = -1;
The response of a "GET" request is cached by default, so to make sure that our example brings back the current time each time it is clicked, this line is crucial. The next few lines change the content type to plain text, get the current time, and writes the output:
Response.ContentType = "text/plain";
Response.Write(DateTime.Now.ToString());
Response.End();
That's it! Now, we can run our sample. Click the "Get Server Time" link, and we should see the current time displayed in an alert box:
So, let's move on to a more complex example: saving data back to the server using an AJAX call.
Sample 2: Saving data to the server
As you may have noticed, in the demo project for download, the "Default.aspx" page does not have the "runat=server
" attribute in the "form
" tag. The reason for this is because ASP.NET doesn't allow nested form
tags. HTML does, however, allow this, and because this next example will use a nested form, we need to remove the "runat=server
" attribute from the "Default.aspx" page. This sample will also use one of the jQuery "plug-ins" that I disused earlier, called the "Form plug-in (with AJAX)" which you can get from here.
Save the plug-in code into a file named "form.js", and include it in the "Default.aspx" page. Here is the additional HTML that we'll be adding to our "Default.aspx" file:
<div style="width:350px">
<div style="background:#CCC"> <a href="#" id="editName">Edit</a></div>
<div id="divView"><asp:literal id="litName" runat="server"/></div>
<div id="divEdit" style="display:none"></div>
</div>
The literal control litName
will be populated from a name held in a Session variable. It is the name held in this session that we'll be editing in this example. Next is the JavaScript we'll be adding to the "Default.aspx" page for this example:
$("a#editName").click(function() {
$.get("ChangeName.aspx", function(response) {
$("div#divEdit").html(response).show();
$("div#divView").hide();
var options = {
method: 'POST',
url: 'ChangeName.aspx',
after: function(response) {
$("div#divView").html(response).show();
$("div#divEdit").empty().hide();
$("a#editName").show();
}
};
//bind to form's onsubmit event
$("form#ChangeName").ajaxForm(options);
//hide the "edit" link
$("a#editName").hide();
//wire up the cancel link
$("a#lnkCancel").click(function() {
$("div#divView").show();
$("div#divEdit").empty().hide();
});
});
});
The first block of code above binds to the "onclick
" event of the link with an ID
of editName
. When this code is executed, we'll retrieve the "ChangeName.aspx" file and display the output in the 'divEdit
' div
tag. We'll also hide the div
tag that contains the "read only" view of this same data (the 'divView
' div
tag):
$("a#editName").click(function() {
$.get("ChangeName.aspx", function(response) {
$("div#divEdit").html(response).show();
$("div#divView").hide();
This last example shows one of the greatest features of jQuery: Chainability. Notice this line of code: $("div#divEdit").html(response).show();
. This line finds the div
tag with an ID
of divEdit
, sets the innerHTML
to the content of the response
variable, and then shows it. To describe chainability in a nutshell: every method within jQuery returns the query object itself, allowing you to 'chain' upon it.
OK, so now the HTML within the "ChangeName.aspx" has been placed into the 'divEdit
' div (form and all) – so now, we need to bind to the "onsubmit
" event and handle it with our Form plug-in. The following code defines our desired settings for the Form plug-in using JSON in the "options
" variable:
var options = {
method: 'POST',
url: 'ChangeName.aspx',
after: function(response) {
$("div#divView").html(response).show();
$("div#divEdit").empty().hide();
}
};
Notice that the above code also specifies the code to execute when a response is received from the form submission, in the "after
" keyword. Now, we can use the Form plug-in's "ajaxForm
" function to bind to the form's "onsubmit
" event:
//bind to form's onsubmit event
$("form#ChangeName").ajaxForm(options);
Lastly, we'll hide the editName
link and bind to the Cancel link's "onclick
" event to get back to our previous state by clearing out the edit form, hiding the editing div
tag, and showing the view div
tag.
//hide the "edit" link
$("a#editName").hide();
//wire up the cancel link
$("a#lnkCancel").click(function() {
$("div#divView").show();
$("div#divEdit").empty().hide();
});
Now, let's take a look at the "ChangeName.aspx" page. Here's the HTML in its entirety (notice the absence of the html
and head
tags). Remember, this page will be loaded into our "Default.aspx" page, so we don't want the html
and head
tags to come with it:
<%@ Page language="c#" Codebehind="ChangeName.aspx.cs"
AutoEventWireup="false" Inherits="AJAXJQuerySample.ChangeName" %>
<form id="ChangeName" method="post" runat="server">
<asp:textbox id="txtName" runat="server"/>
<input type="submit" value="Save" id="Submit1" name="Submit1"/> or
<a href="#" id="lnkCancel">Cancel</a>
</form>
And, here is the code-behind file:
protected System.Web.UI.WebControls.TextBox txtName;
private void Page_Load(object sender, System.EventArgs e)
{
if (Page.IsPostBack)
{
ProcessForm();
}
else
{
string existingName;
if (Session["testName"] == null)
{
Session["testName"] = "John Smith";
}
existingName = Session["testName"].ToString();
txtName.Text = existingName;
}
}
private void ProcessForm()
{
string newName = txtName.Text;
Session["testName"] = newName;
Response.Clear(); //clears the existing HTML
Response.ContentType = "text/plain"; //change content type
Response.Write(newName); //writes out the new name
Response.End(); //end
}
Note that we just need to use a regular <input type=submit id="Submit1" name="Submit1">
tag to submit the form instead of an <asp:button>
web control. This is because of the submission being handled by jQuery. In the code-behind, we just need to detect a postback and handle the form submission from there:
if (Page.IsPostBack)
{
ProcessForm();
}
else...
The "ProcessForm
" method is called, which handles the form submission and outputs the updated name:
string newName = txtName.Text;
Session["testName"] = newName;
Response.Clear(); //clears the existing HTML
Response.ContentType = "text/plain"; //change content type
Response.Write(newName); //writes out the new name
Response.End(); //end
That's it! Now, we can run our sample. Click the "Edit" link and the new form is loaded in. Change the name and click the "Save" button, and the updated name is sent back and displayed.
Step 1: Click the "Edit" link:
Step 2: Change the name and click "Save":
Step 3: View the updated name:
Conclusion
I have been using these techniques extensively, in my latest developments, to great success. I went this route because the new Microsoft AJAX tools were still in beta when I started, and I didn't want to hassle with the changes down the road. Again, I'm not claiming this to be a better solution than Microsoft AJAX (I've not done any comparisons), but if you're looking for another alternative, I would definitely suggest this technique. I've really enjoyed using jQuery, and have found that it makes it really easy to hook into the code wherever I want to add things like animations. Since switching to the jQuery JavaScript library, I now write about 10% the amount of JavaScript that I used to.