Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / XHTML

(Re) Introducing AJAX for ASP.NET with Prototype

4.90/5 (16 votes)
17 Dec 2008CPOL10 min read 62.2K   449  
Writing and using cross platform AJAX in ASP.NET applications.

AJAXMadeSimple

Introduction

The ASP.NET platform is undeniably a server centric model, and it was never intended to execute client intensive logic such as Asynchronous JavaScript and XML (AJAX). In order to provide an AJAX framework to the .NET community and not alienate developers who have spent a career programming against this server based architecture, Microsoft needed to figure out a way to make client JavaScript easy to develop using the existing server controls standard. Ultimately, they delivered an AJAX framework for ASP.NET that gives .NET developers a taste of what many developers had been enjoying for quite some time.

It's important to understand that the ASP.NET AJAX is one of many frameworks out there, and there are a lot of AJAX frameworks (more than 100).

This article demonstrates how to use an alternate JavaScript/AJAX framework for AJAX development in ASP.NET applications.

JavaScript & The Prototype Framework

Though the scope of this article is narrowly focused on AJAX, I want to spend a little time discussing JavaScript and why frameworks which wrap JavaScript exist.

Up until web technology exploded, seemingly overnight, nearly all developers created code designed for a specific target platform. The tools that they used implemented the specifications of the language effectively, and they could focus their energy on performance and optimization routines. Writing JavaScript, on the other hand, can be painful and tedious, not because of the language, but because the APIs used by other languages to communicate with JavaScript, though standardized, are not fully implemented by every platform. In other words, there are some browsers than can do things that other browsers can't.

Some platforms have even mis-implemented certain specifications (such as the DOM spec in IE) that can lead to memory leaks and other very difficult problems to troubleshoot. A developer can easily spend half of his workday developing multi-platform JavaScript code, and the other half debugging it. It just doesn't make sense to most developers to even bother with JavaScript, even if the gains in application performance could be significant.

Not wanting to give up on JavaScript's potential, many developers began to write "helper" methods that would perform monotonous tasks such as checking browser versions and setting variables based on browser versions. Some of these "helper" frameworks began to get shared, peer reviewed, and optimized to the point where they could be considered enterprise frameworks. The Prototype framework is one of these frameworks that is now widely used and highly respected. In fact, it is used commercially by NASA, CNN, Ruby On Rails, and Apple.

Prototype isn't a widget, UI, or component library such as script.aculo.us, it's the engine that powers component libraries. Prototype is the foundation for which many libraries are layered onto. It's not about any concrete implementation (such as a drag and drop AJAX control), it's about the abstraction and Object Oriented Programming (OOP) principles that allow you to build these controls in the quickest, more reliable way possible.

When you start using Prototype and begin to understand its simplicity and elegance, it becomes difficult to go back to plain old JavaScript.

Further reading:

AJAX & The Prototype Framework

Of course, AJAX is Asynchronous JavaScript and XML, and all it really means is the developer is leveraging the JavaScript XmlHttpRequest object. This object allows the browser to initiate page requests outside the standard page request scope. More importantly, it allows you to refresh parts of the page without refreshing the whole page. The XmlHttpRequest object lives on the client side, and shuttles data to and from the server without any interference from the hosting web server. The XmlHttpRequest is not intuitive, and it can be very frustrating to use, especially when dealing with known issues across browsers (not to mention having to write mountains of code). Prototype does an excellent job dealing with all this for us and exposing a simple and powerful AJAX API that covers nearly all of the raw AJAX functionality developers want.

Prototype exposes a clear AJAX interface for us to leverage. The methods provided are:

For the purposes of this article, we're going to use the Ajax.PeriodicUpdater and Ajax.Request methods since there is overlapping functionality between members and these are the most used calls in Prototype's AJAX wrapper.

Samples

The intent of the samples is to demonstrate various methods for using asynchronous partial postback in your applications with the Prototype framework. When it comes to AJAX development, nearly all of it is used for the same purposes:

  • Update an area on a page asynchronously as a response to an event on the page (button-click, etc.) and refresh just that area.
  • Update an area on a page asynchronously on a timer and refresh just that area.

The included samples consist of two parts each; the client user interface and the server script. It works like this: the ClientUI.aspx page is used by the client as they would use any other page. When they interact with an AJAX control, the control asynchronously executes 'GET' requests to the server script, and based on the response from the server, the AJAX control quietly updates the areas of the page that need updating.

The samples included are:

  • Quote Ticker
  • The quote ticker project uses the Ajax.PeriodicUpdater Prototype method to update an area of the page asynchronously based on a timed interval. The solution consists of a server script which fetches the quotes from a text file and a client page that uses AJAX to execute "GET" requests against the server script every 5 seconds.

  • Auto Suggestions
  • The Auto-Suggestion project introduces the Ajax.Request Prototype method which is used to execute AJAX requests based on events. In this case, when the user types letters into the AJAX enabled input, an event is triggered which runs an asynchronous "GET" request to the server script in order to locate matching records in an XML file. The user is presented with a list of suggestions as they type into the input, and if they click on a suggestion, a JavaScript function is called to try to play the selected record in Windows Media Player.

  • Media Player
  • The Music/Movie player project also uses the Ajax.Request Prototype method, but no server script is needed for it to work. For this sample, we use an existing XML file and interact with it directly from JavaScript, omitting the need for a server-side processor.

The prototype.js framework is included with the samples in the /AJAXMadeSimple/js folder.

Quote Ticker

Note: This sample can be found in /AJAXMadeSimple/AJAXRandomQuote.

The AJAXRandomQuote project demonstrates how we use the PeriodicUpdater method in the Prototype library to create an area of a page that updates itself on a timed interval. We're using famous quotes for this purpose, but it's commonly used for news and RSS items and stock listings.

QuoteScript.aspx (server script)

ASP.NET
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.IO" %>

<script runat="server" >
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.ContentType = "text/plain";
        Response.CacheControl = "no-cache";
        Response.AddHeader("Pragma", "no-cache");
        Response.Expires = -1;
        
        Random rnd = new Random();
        List<string> qs = GetQuotes();
        Response.Write(qs[rnd.Next(qs.Count)]);
    }

    private List<string> GetQuotes()
    {
        List<string> q = new List<string>();
        string qfile = Server.MapPath("quotes.txt");

        if (File.Exists(qfile))
        {
            using (StreamReader sr = new StreamReader(qfile))
            {
                string line = string.Empty;
                while ((line = sr.ReadLine()) != null)
                {
                    if (!string.IsNullOrEmpty(line))
                        q.Add(line);
                }
            }
        }
        return q;
    }    
</script>

The script above is used to read from a text file on the server and return a random line to the client (each time the script is executed). Note the existence of the ContentType, CacheControl, and Header properties that must be set for the sample to work correctly. We have to force the server to reject caching (of any kind) to ensure our client gets a new quote every few seconds. Of course, we could get this data anywhere (database, XML file, text file, etc.).

Further reading: MSDN - How To Prevent Internet Explorer From Caching.

ClientUI.aspx (client page)

ASP.NET
<%@ Page Language="C#"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Untitled Page</title>
    <script src="../js/prototype.js" type="text/javascript"></script>
</head>
<body>
<div id="quote"></div>
<p>
<input type="button" onclick="stopPolling()" value="Stop Ajax" /> 
<input type="button" onclick="startPolling()" value="Start Ajax"  />
    
<script language="javascript" type="text/javascript" >
var poller;

poller = new Ajax.PeriodicalUpdater('quote', 'QuoteScript.aspx', {
  method: 'get', frequency: 5
});

function stopPolling() {
  poller.stop();
  $(quote).innerHTML = "Asynchronous JavaScript Stopped";
}

function startPolling() {
  poller.start();
}

</script>
</body> 
</html>

You can see this is a very simple page that consists of a #div area on the page to hold our quote, a few input button controls, and the AJAX periodicUpdater.

C#
new Ajax.PeriodicalUpdater(container, url[, options])

We have defined the container parameter as quote (our #div area) and the parameter url as QuoteScript.aspx (our server script). We're using the options: method and frequency. Method defines our action and the frequency defines the update time in seconds. In effect, we want to receive a new quote from the server every 5 seconds.

Further reading:

Auto-Suggestion Text Input

Note: This sample can be found in /AJAXMadeSimple/AJAXAutoSuggestBox.

One of the most exciting features in AJAX is the ability to do work behind the scenes without the user's experience being interrupted. This asynchronous processing allows you to do wonderful things to improve user satisfaction (e.g., suggesting searches, and auto-completing dropdown lists). The AJAXAutoSuggestBox project demonstrates how we can suggest searches to users as they're typing into the search field. The suggestions originate from the response of the server script (which is reading an XML file).

ServerSearch.aspx (server script)

ASP.NET
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Xml.Linq" %>
<%@ Import Namespace="System.Linq" %>

<script runat="server" >
    protected void Page_Load(object sender, EventArgs e)
    {
        //You must specify the ResponseType as Xml
        Response.ContentType = "text/xml";
        string qs = Request.QueryString["q"];
        
        if (!string.IsNullOrEmpty(qs))
        {
            //Search the Xml data source and create the response
            Response.Write("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
            Response.Write("<music>");
            XDocument xdoc = XDocument.Load(Server.MapPath("player.xml"));
            var query = from s in xdoc.Elements("music").Elements("Track")
                        where s.Attribute("url").Value.Contains(qs)
                        select s;

            foreach (XElement xe in query.ToList())
                Response.Write(xe.ToString());

            Response.Write("</music" + ">");
        }
    }    
</script>

This server script is a little more advanced than the last one because we need to return properly formed XML to our AJAX client. Take note of the Response.ContentType property as it must specify that the server response is XML and not plain text or HTML. We're using the new System.Xml.Linq classes to do a quick and dirty search of an XML file, and then we're creating a new XML file that only contains the results of the query (to feed back to the AJAX client request).

Further reading:

ClientUI.aspx (client page)

ASP.NET
<%@ Page Language="C#"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server"><title>Partial Page Post Back Example - Music Player</title>
<script src="../js/prototype.js" type="text/javascript"></script>
</head>
<body>
<input type="text" id="q" onkeyup="search()"  />
<div id="songs" ></div><p> </p>
<div id="player"></div>
    
<script language="javascript" type="text/javascript" >
function PlaySong(url)
{
  $('player').innerHTML = '';
  var m_embed = document.createElement('embed');
  m_embed.src = url;
  $('player').appendChild(m_embed);
}

function search() {
new Ajax.Request('ServerSearch.aspx?q='+escape($F('q')), {
  method: 'get', 
  onSuccess: function(transport) {
    var trackXml = transport.responseXML.getElementsByTagName('Track');
    
    $('songs').innerHTML = '';

    for(var x = 0; x < trackXml.length; x++) {
      var url = trackXml[x].getAttribute('url');
      var title = trackXml[x].getAttribute('title');
      var artist = trackXml[x].getAttribute('artist');
      
      var html = '<a href="javascript:void PlaySong(\''+ url +'\');" class="link">';
      html += artist + ' - ' + title +'</a><br />';
      $('songs').innerHTML += html;
      }
    }
  } );
}        
</script>
</body> 
</html>

This client script is also a bit more advanced than the previous client script, but if you look at it closely, you'll see that it's actually quite simple. We define an input text field that runs the search() function each time a key is entered, a #div element to store the AJAX auto-suggestions, a #div element to store the Windows Media Player (WMP), and two JavaScript functions:

  • PlaySong(url)
  • You can actually discard this entirely if you don't want to see AJAX media playback. It only works in IE, and all we're doing is creating an embed element in our player #div and telling the embedded media player where the music file we want to play is.

  • search()
  • The search function introduces the Ajax.Request prototype method (the most used method in the library).

JavaScript
new Ajax.Request(url[, options])

We are specifying the ServerSearch.aspx page as our URL (with a querystring based on the value of the search input field), and we're using the options parameters: method and onSuccess. If the request was successful, we're assigning the response XML stream from the server to a variable (trackXml). We enumerate the response XML stream, and extract the elements we need to create a list of matched songs, and we create the links needed to playback the selected tracks.

player.xml (data-source)

XML
<?xml version="1.0" encoding="utf-8" ?>
<music>
  <Track url="03_metallica_-_broken_beat_scarred.mp3" 
         artist="Metallica" title="Broken, Beat, Scarred"></Track>
  <Track url="05_metallica_-_trapped_under_ice.mp3" 
         artist="Metallica" title="Trapped Under Ice"></Track>
  <Track url="06_metallica_-_harvester_of_sorrow.mp3" 
         artist="Metallica" title="Harvester of Sorrow"></Track>
</music>

Further reading:

AJAX Music/Movie Player

Note: This sample can be found in /AJAXMadeSimple/AJAXMusicPlayer.

The AJAXMusicPlayer project is a simpler off-shoot of AJAXAutoSuggestBox. In this project, we don't need a server script to do any processing for us because we're going to use an existing XML data source on the server. As the case above, the actual playback of music or movies in an HTML embed tag relies on using a browser that supports it (such as IE), and in the real world, you would never do this, but it's an effective demonstration of how AJAX can power your business solutions.

As stated above, no server script is needed for this sample.

ClientUI.aspx (No server script needed!)

ASP.NET
<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Partial Page Post Back Example - Music Player</title>
    <script src="../js/prototype.js" type="text/javascript"></script>
    <link href="player.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="songs" class="songs"></div><p></p>
<div id="player"></div>
    
<script language="javascript" type="text/javascript" >
function PlaySong(url)
{
  $('player').innerHTML = '';
  var m_embed = document.createElement('embed');
  m_embed.src = url;
  $('player').appendChild(m_embed);
}

new Ajax.Request('player.xml', {
  method: 'get',
  onSuccess: function(transport) {
    var trackXml = transport.responseXML.getElementsByTagName('Track');
    
    $('songs').innerHTML = '';

    for(var x = 0; x < trackXml.length; x++) {
      var url = trackXml[x].getAttribute('url');
      var title = trackXml[x].getAttribute('title');
      var artist = trackXml[x].getAttribute('artist');
      
      var html = '<a href="javascript:void PlaySong(\''+ url +'\');" class="link">';
      html += artist + ' - ' + title +'</a><br />';
      $('songs').innerHTML += html;
      }
    }
  }  );        
</script>
</body>
</html>

This is more or less the exact same script as the AJAXAutoSuggestBox except we're specifying the XML file to use, there's no input field, and the list of tracks are displayed when the page loads. When we click on a track, the URL is placed in an embed element and the track begins to play. All this logic executes with no page postbacks or re-rendering. It's all performed on the client side.

Refer to the AJAXAutoSuggestBox section above for additional explanation and further reading resources.

player.xml (data-source)

XML
<?xml version="1.0" encoding="utf-8" ?>
<music>
  <Track url="03_metallica_-_broken_beat_scarred.mp3" 
         artist="Metallica" title="Broken, Beat, Scarred"></Track>
  <Track url="05_metallica_-_trapped_under_ice.mp3" 
         artist="Metallica" title="Trapped Under Ice"></Track>
  <Track url="06_metallica_-_harvester_of_sorrow.mp3" 
         artist="Metallica" title="Harvester of Sorrow"></Track>
</music>

Further reading:

Scriptaculous

As mentioned earlier, script.aculo.us is a powerful framework that sits on top of prototype.js and delivers amazing special effects like animation, drag and drop, DOM and Unit Testing, and a mountain of other awesome features. If this article is well received, I can write a similar article with examples for using Scriptaculous in ASP.NET.

Conclusion

In this article, we demonstrated how to implement powerful AJAX features into an ASP.NET website without requiring the ASP.NET AJAX framework. The possibilities are endless with the Prototype framework, and very little JavaScript knowledge is actually required to start getting results right away.

History

  • 12/17/2008 - Article submitted.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)