AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=1748&pId=-1
Build an AJAX Based ASP.NET Web Tag Application - Part 1
page
by Xianzhong Zhu
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 45141/ 200

Introduction

Nowadays, AJAX is one of the coolest features for building interactive browser-based Web 2.0 applications. As you have seen, Blogs, Tags, RSS, NAS, XML based Forums, Ajax Mails, etc. are rushing to every web surfer. In this series of articles (two parts), I will lead you to use the two famous Ajax frameworks, Prototype and script.aculo.us, to develop a web tag application under the ASP.NET 3.5 environment. In this first part, we will familiarize ourselves with the fundamentals of the two Ajax frameworks, the functionality requirements, and the database design of the system.

What are Web Tags

Maybe some of you feel puzzled with the web tag concept; however, you are sure to be quite familiar with the browser's Favorites or Bookmarks. In fact, the web tag is one of the typical web 2.0 applications, which provides the support of persisting all of your things in you former favorites in the remote website. In the new way, users only need to put their collected website URL's on the Internet and maintain the URL categories appropriately. One of the outstanding merits of this solution is users cannot lose the favorite URL's any more due to the system reloading or any other possible damages to the system. Moreover, the users can also share their favorite URL's with other friends all over the world.

Today, there are already many mature websites providing the web tag support, some famous ones include:

Del.icio.us (http://del.icio.us), which is possibly the earliest web tag system that uses tag as the bookmark category, and also the web tag services most used as of now.

Furl (http://www.furl.net), which adopts the category and key words to identify the tags.

Blinklist (http://www.blinklist.com), which fully utilizes the Prototype and script.aculo.us Ajax frameworks in terms of the interface design. It maybe one of most successful Ajax based web projects now.

Google Notebook (http://www.google.com/notebook) is Google's newly-released web tag service, with the Google-styled persistent support - convenient and brisk manipulation and simple and clear functionalities. One of the most prominent features of Google Notebook is it can add the contents (pictures and words) of the web pages into the web tags so as to facilitate the viewing of the tags. And of course, it fully leverages Ajax related techniques to bring to bring a friendly experience to people.

In terms of the developing techniques, different websites adopt different ones. Some systems leverage the traditional web programming techniques and use the browser provided bookmark function to add the URL's into the web tag system, such as del.icio.us. In contrast, other new websites, such as Google Notebook, use as many as possible Ajax associated techniques to increase the availability of the system, as well as provide related browser add-ins to simplify the adding tag operations, by which users do not need to enter info manually.

In the aspect of applicability, the system to build in this article quite resembles Google Notebook. It takes the classifying mode to manage the web tags, as well as support the typical operations, such as adding, editing, and removing tags.

Before starting the real work, you should familiarize yourself with the two Ajax frameworks, Prototype and script.aculo.us.

Introduction to Prototype

Prototype is a popular fundamental library of reusable JavaScript code, which provides helpful methods and objects that extend JavaScript in a safe and consistent way. Its clever Ajax request model simplifies various cross-browser developments.

For brevity, we are only interested in the Ajax related support by Prototype. As for other concepts, in later sample code we will discuss them.

As an Ajax framework, Prototype provides powerful support concerning various Ajax techniques. In sum, there are the following Ajax related classes and objects introduced in Prototype: Ajax, Ajax.Responders, Ajax.Base, Ajax.Request, Ajax.PeriodicalUpdater, and Ajax.Updater.

Figure 1 - The relationships between the main Ajax classes inside Prototype

In general, the four sub classes in green rectangles in Figure 1 are mostly used. Herein, we plan to reject theories with them, but look at some basic samples relating to the several important classes to lay a firm foundation for the later web tag project.

Sample for Ajax.Request

Probably the most frequently used Ajax class in Prototype is class Ajax.Request. Since the ten or so methods defined in class Ajax.Request are generally used internally, we are not going to discuss them in detail, but turn to see how to use the class Ajax.Request in real cases.

Listing 1 - Sample for the Ajax.Request class

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 
 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
 transitional.dtd">
<html>
      <head>
            <title> Sample for the Ajax.Request class </title>
            <script type="text/javascript" language="javascript"
             src="prototype.js" ></script>
            <script type="text/javascript" language="javascript">
            function test() {
                  var myAjax = new Ajax.Request(
                        'http://www.sergiopereira.com/articles/prototype.js.html', 
                        {
                              method: 'get', 
                              onComplete: showResponse
                        }
                  );
            }
            
            function showResponse(response) {
                  $('divResult').innerHTML = response.responseText;
            }
            
            var handle = {
                  onCreate: function() {
                        Element.show('loading');
                  },
                  onComplete: function() {
                        if (Ajax.activeRequestCount == 0) {
                              Element.hide('loading');
                        }
                  }
            };
            Ajax.Responders.register(handle);
            </script>
      </head>
      <body>
      <input type="button" value="click" onclick="test()" />
      <div id="divResult" ></div>
      <div id='loading' style="display:none">
            <img src="loading.gif">Loading...
      </div>
      </body>
</html>

The most important code herein focuses on the test() function. As you have seen, two arguments () are required to initialize the Ajax.Request object. The first argumentrepresents the url of the requested web page (in this case a simple static page "data.html"). The second argument relates to the options that the Ajax operation requires. Note, Prototype has not defined a special class for the Ajax options, but uses an anonymous object to set up the Ajax required parameters. In this sample, there are only two parameters: method indicates the HTTP request mode (by default "POST"), onComplete identifies the callback function to be executed after the Ajax operation returns successfully (i.e. the status of the XMLHttpRequest object equals to 4). In fact, there are still other parameters for the Ajax related operation, and you can refer to the complete official materials here.

For integrity, we have also listed the content of file data.html above, as follow:

some data....

Pretty easy, there is only a short string in it!

Let us next continue with another class, Ajax.Updater.

Sample for Ajax.Updater

In the above Listing, we have succeeded in locally updating a web page by using the "Ajax.Request" class. Due to this kind of functionality, it is often used and for simplification, Prototype derives another sub class "Ajax.Updater" from the parent class "Ajax.Request." In contrast to the "Ajax.Request" class, another parameter container is added to "Ajax.Updater," which represents the id property of the page element to update. Listing 2 illustrates the usage of class Ajax.Updater through which the partial updating in Listing 1 becomes simpler.

Listing 2

…… (omitted)
<head>
    <title>Untitled Page</title>
        <script type="text/javascript" language="javascript"
             src="prototype.js" >
             </script>
             
            <script type="text/javascript" language="javascript">
            function test() {
                  var myAjax = new 
                Ajax.Updater(
                'divResult', // the page element to update
                        'data.html', 
                        {
                              method: 'get', 
                        }
                  );
            }
            </script>
</head>
<body>
          <h1>Sample for the Ajax.Updater class</h1>
          <input type="button" value="click" onclick="test()" />
          <div id="divResult" ></div>
</body>
</html>

Obviously, the code here gets greatly simplified.

In fact, the Ajax.Updater class still owns another function: if the requested page contains some JavaScript code, then the Ajax.Updater can execute the code in it provided we set the property evalScripts to true in the options. For brevity, we will move on to the next topic.

Next, let us continue to see the third important Ajax related class - Ajax.PeriodicalUpdater.

Sample for Ajax.PeriodicalUpdater

Similar to the Ajax.Request class, the Ajax.PeriodicalUpdater class also derives from class Ajax.Base. In some typical Ajax applications, periodically updating some elements on the page is generally required, such as in weather broadcast or live news applications. Before, to achieve such functionality, you usually needed to use the JavaScript's timer related functions, such as setTimeout or clearTimeout. With the help of class Ajax.PeriodicalUpdater, this kind of coding will get drastically simplified.

Similar to class Ajax.Updater, Ajax.PeriodicalUpdater also supports dynamically executing JavaScript codes supposing the Ajax option parameter evalScripts is set to true.

Moreover, Ajax.PeriodicalUpdater introduces another two special Ajax options: frequency and decay. frequency is easy to follow, which specifies the time interval to update some page elements or execute some scripts. However, in special cases, the time interval may not always be fixed when parameter decay comes to help. If the data requested to return is the same as the last time, then the next Ajax operation time will multiply by a coefficient specified by decay.

To gain a more intuitive understanding with the property decay, let us take a related sample (Listing 3).

Listing 3

……(omitted)
<head>
    <title>Untitled Page</title>
        <script type="text/javascript" language="javascript"
             src="prototype.js" >
             </script>
             
            <script type="text/javascript" language="javascript">
            var count = 0;
            function test() {
                  var myAjax = new Ajax.PeriodicalUpdater(
      'script1.html', //the requested url 
      {
            method: 'get',//HTTP request mode
            evalScripts: true, //whether to execute the script in the page
            frequency: 1, //specify the page updating frequency
            decay: 2 //the decaying coefficient
      }
                  );
            }
            </script>
 …… (omitted)   
</head>
<body>
    <h1>Sample for the Ajax.PeriodicalUpdater class</h1>
    <input type="button" value="click" onclick="test()" style="width: 41px" />
    <div id="divResult" ></div>
    <div id="divResult2" ></div>
</body>

Here, we also list the code for file script1.html for your reference.

Listing 4

<script language="javascript" type="text/javascript">
//count the times of Ajax.PeriodicalUpdater calling
count++;
//add a line inside element divResult2
//to record the datetime and 
//the times of Ajax.PeriodicalUpdater calling
var str = $('divResult2').innerHTML;
$('divResult2').innerHTML = str + "count = " + count + ": " + new Date() + "<br>";
</script>

As you have seen, we purposely added the time related script inside file script1.html for you to see the effect of property decay more clearly. Lastly, let us take a look at one of the running-time snapshots for this sample (Figure x).

Figure 2 - Sample for Ajax.PeriodicalUpdater

As you have seen from Figure 2, because the data requested stayed the same, the requesting time interval becomes double of that of the last time. However, once the requested data changes, the requesting time interval is restored to the original value.

Sample for Ajax.Responders

Sometimes, we might want to automatically show an indicator when an AJAX request is ongoing, and hide it when none are. You may well want to factor out exception handling as well, logging those somewhere on the page in a custom fashion. In all these cases, the Ajax.Responders class comes to help. Ajax.Responders lets you register (and if you wish to, unregister later) responders, which are objects with properly-named methods. These names are in fact the regular callback names, and your responders can implement any set of interest.

The example in Listing 4 is created based upon that in Listing 1, which illustrates one of the most typical usages of class Ajax.Responders.

Listing 5

<!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>Sample for the Ajax.Responders class</title> 
 
        <script type="text/javascript" language="javascript"
             src="prototype.js" >
             </script>
             
            <script type="text/javascript" language="javascript">
            function test() {
                  var myAjax = new 
                Ajax.Request(
                        'data.aspx', 
                        {
                              method: 'get', 
                              onComplete:showResponse
                        }
                  );
            }
            
            function showResponse(response) {
                  $('divResult').innerHTML = response.responseText;
            }
            
            var handle = {
                  onCreate: function() {
                        Element.show('loading');
                  },
                  onComplete: function() {
                        if (Ajax.activeRequestCount == 0) {
                              Element.hide('loading');
                        }
                  }
            };
            Ajax.Responders.register(handle);
            </script>
      <style type="text/css">
        #divResult
        {
            height: 45px;
            width: 303px;
            border-style: inset;
            border-color: #008000;
            background-color: #808080;
            color: #FF0000;
        }
    </style>
      </head>
      
      <body>
          <H1>Sample for the Ajax.Responders class</H1>
          <input type="button" value="click" onclick="test()" />
          <div id="divResult" ></div>
          <div id='loading' style="display:none">
                <img alt="img1" src="loading.gif"/>Loading...
          </div>
      </body>
</html>

In this case, we used the method register of class Ajax.Responders to register a set of callback functions: onCreate is called during the Ajax request process and onComplete is called when the Ajax request succeeds. And further by programming the two callback functions, we successfully achieved the effect of prompting the user the Ajax request process using an intuitive .gif animation. Note the requested url is changed into "data.aspx," through which we can more conveniently simulate the server side delay using the Sleep function. The following lists the code for file data.aspx.cs:

Listing 6

protected void Page_Load(object sender, EventArgs e)
{
  System.Threading.Thread.Sleep(3000);
  Response.Write("Data returned from the server...");
}

Lastly, the following Figure indicates one of the running time snapshots during the Ajax request process.

Figure 3 - Sample for Ajax.Responders

Next, let us take a quick look at another Ajax framework, script.aculo.us, which our web tag application rests on to gain more friendly visual effects.

Introduction to script.aculo.us

script.aculo.us is another set of JavaScript libraries, which is based on Prototype, offers handy pre-fabricated widgets to enhance the user interface of web sites. It provides a visual effects engine, a drag and drop library (including sortable lists), a couple of controls (Ajax-based autocompletion, in-place editing, and sliders) and more. As of January 3, 2008, script.aculo.us upgrades to version 1.8.1. For small and mid-sized web projects, script.aculo.us+Prototype are a recommendable solution.

I am going to only introduce two objects, Sortable and Ajax.Autocompleter, in script.aculo.us by respective examples for brevity and their being used later on.

Sample for object Sortable

According the script.aculo.us wiki document, Sortable is a quick way to initialize many Draggable elements in a container element. When you create a new Sortable, it takes care of the creation of the corresponding draggable Droppables. The main syntax of Sortable is as follows:

Sortable.create('id_of_container',[options]);

As you may imagine, the powerful function is hidden inside parameter "options." However, we only give a basic illustration of object Sortable in the following sample.

Listing 7

<body>
<h1>Demo for Sortable.create</h1>
<ul style="position: relative;" id="list" class="sortablelist">
 
<li id="Tags_1" class="sortablelist" style="position: relative;">
<img alt="move element up"  src="images/arrow_up_blue.png" class="arrowbutton"/>
<img alt="move element down" src="images/arrow_down_blue.png" 
  style="margin-right: 20px;" class="arrowbutton"/>Prototype</li>
 
<li id="Tags_2" class="sortablelist" style="position: relative;">
<img alt="move element up"  src="images/arrow_up_blue.png" class="arrowbutton"/>
<img alt="move element down"  src="images/arrow_down_blue.png" 
  style="margin-right: 20px;" class="arrowbutton"/>script.aculo.us</li>
 
<li id="Tags_3" class="sortablelist" style="position: relative;">
<img alt="move element up"  src="images/arrow_up_blue.png" class="arrowbutton"/>
<img alt="move element down"  src="images/arrow_down_blue.png" 
  style="margin-right: 20px;" class="arrowbutton"/>Dojo</li>
 
<li id="Tags_4" class="sortablelist" style="position: relative;">
<img alt="move element up"  src="images/arrow_up_blue.png" class="arrowbutton"/>
<img alt="move element down" src="images/arrow_down_blue.png" 
  style="margin-right: 20px;" class="arrowbutton"/>jQuery</li>
</ul>
 
<script type="text/javascript" >
 Sortable.create("list", {
     ghosting: true,
     constraint: false
 });
 </script>
</body>

Here, the first parameter "list" specifies the sortable element, while the second parameter corresponds to an object that holds a possible large set of options. Here, property ghosting specifies whether to keep the copy at the original position when dragging an element, the second property constraint indicates the moving direction (the default value is vertical, and the other two are horizontal and false respectively). Figure 4 illustrates the two snapshots before and after moving the item in a list.

Figure 4 - Demo for Sortable.create usage

Next, let us take a look at the Ajax related topic provided by script.aculo.us.

Sample for object Ajax.Autocompleter

There are three Ajax controls in script.aculo.us, which are Ajax.Autocompleter, Ajax.InPlaceEditor, and Ajax.InPlaceCollectionEditor, respectively. Here, we only show interest in the first one.

Today, maybe Google Suggest becomes the doctrine when one mentions AJAX. script.aculo.us, of course, provides the kind of support through two means of automatic completion, which are achieved through two classes, Ajax.Autocompleter and Autocompleter.Local. The distinction lies in that the former deals with the listed data coming from the server, while the latter works with data preset using client-side scripts.

Here, we only care for class Ajax.Autocompleter, whose syntax is defined below:

new Ajax.Autocompleter(id_of_text_field, id_of_div_to_populate, url, options);

In the following example, there are two elements introduced. The <input/> element is used to enter a character string, the <div/> element is used to display the dropdown list.

Listing 8

<input type="text" id="autocomplete" name="autocomplete_parameter" />
<div id="autocomplete_choices" class="autocomplete"/>

Then, in the JavaScript block, we have defined an Ajax.Autocompleter object, as follows:

Listing 9

new Ajax.Autocompleter
(
"autocomplete",
"autocomplete_choices",
"list.html", {
method: "GET",
tokens: ","
}
);

The first two parameters correspond to the above page elements. The third parameter specifies the URL of the Ajax request, through which Ajax.Autocompleter will assign the returned data from this request to the innerHTML attribute of the dropdown list element defined above. The last parameter relates to a set of options. Herein, we specify the request mode to be GET and the list separator of many entering data is "'". For more options, please refer to the URL. Figure 5 shows one of the running-time snapshots for this sample.

Figure 5 - Demo for Ajax.Autocomplete

So much for the rough introduction to the two above client-side Ajax frameworks!

Next, we will roll up our sleeves to start the real work - developing a basic web tag system using the two Ajax frameworks. First of all, let us familiarize ourselves with the functionality requirements of the target system.

System Functionality Requirements

As mentioned above, a web tag system will perform the task of storing your favorite URL's in the remote host instead of the local one to prevent some damages from reinstalling your machine or facilitate your access from outside your home or office. On the whole, the web tag system in this article will achieve the listed goals, as follows:

·         Displaying the web tag category list

·         Moving the web tag category

·         Displaying the web tag list

·         Moving a web tag

·         Removing a web tag

·         Adding a new web tag category

·         Removing a web tag category

·         Modifying a web tag category

·         Adding a new web tag

·         Modifying a new web tag

These are the basic functionalities a web tag application should accomplish. Besides these, to facilitate the users' operation, all the functionalities are achieved within one web page using Ajax techniques. In this case, we have recurred to the script.aculo.us framework to achieve special page effects. During the course of accessing the page objects and event binding, we have fully leveraged the support of the Prototype framework, such as the event mechanism, CSS selector, etc.

With the general goals in mind, let us next shift our attention to the database design.

Database Design

For simplicity and just for illustration, I used SQL Server 2005 Express Edition as the backend database. As a typical and efficient solution, I have also utilized stored procedures to encapsulate most of the fundamental business operations. To follow along with the basic idea of the web tag project in this article, you need to download the source files at the end of this article.

In this article, we will design a database named Database.mdf, which contains two tables - section for tag categories and note for tag info, respectively.

Designing the Data Tables

For simplicity, let us use a figure to illustrate the structures for table note and section, as shown in Figure 6.

Figure 6 - Structures and relations for table note and section

Since the database diagram in the source code also contains the explanation for each of the fields of the two tables above, let us continue to discuss the stored procedures in this database.

Designing the Stored Procedures

In traditional ASP.NET applications, the stored procedure is the typical solution relating to the backend database to achieve the three-tier based architecture. To achieve the above listed functions, we have also leveraged the stored procedure to encapsulate the ground floor data operations.

In this web tag application, there are 9 stored procedures, which are AddNote, AddSection, DeleteNote, DeleteSection, EditNote, RenameSection, MoveNote, TransferNote, and MoveSection, respectively. The following gives their related short explanations:

·         AddNote: add the tag info to the system

·         AddSection: add the tag category info to the system

·         DeleteNote: delete the tag info from the system

·         DeleteSection: delete the tag category info from the system

·         EditNote: edit the existing tag info in the system

·         RenameSection: rename the tag category in the system

·         MoveNote: move the existing tag between the tags to change its order in the system

·         TransferNote: move an existing tag from a category to another category in the system

·         MoveSection: change the order between the tag categories

Still for brevity, we do not plan to list the related scripts for the above stored procedures, while you can refer to the source code for details.

Next, we will shift to examineing the system design and the related architecture.

Introduction to the System Design

In a typical Ajax based web application, the relatively complex functionalities usually are performed on the client side. What the server side requires to do is generally limited to carry out the operations according to the requests sent from the client side or return the relevant data, while the client-side JavaScript code will render or update the page according to the states returned from the server and other data info.

Note the sample tag system is constructed based on the ASP.NET 2.0/3.5 platform. So, as you will doped out, the server-side jobs are mainly to provide an interface for the backend database access and to provide the facilitation for the client-side JavaScript code to access the server-side page in the Ajax way so as to access the database.

In this sample, in terms of database, we have utilized the existing ripe and steady Microsoft Enterprise Library. With the help of Microsoft Data Access Application Block, the database associated programming is drastically simplified. In fact, if you are a Java/PHP fan (non-familiar with the .NET platform) you can also easily achieve your target by the similar server-side programming.

Herein, for readers to gain a clearer sight into the system, let us also illustrate the related architecture diagram, as shown in Figure 7.

Figure 7 - The rough architecture of the system

The web tag system in this article holds only one page (any other pages just serves as the server-side web gates without providing .aspx contents). Figure 8 indicates one of the running time snapshots of the main and only page.

Figure 8 - One of the running time snapshots of the web tag system

As shown from the above figure, the left part is the list of the web tag categories. If you click some tag category, the corresponding tag details will be displayed at the right side. Herein, you can drag either the tag category or the tag item to change its displaying order. Moreover, you can modify them in the Ajax mode. And also, adding new tag categories and tag info are all performed in the Ajax style to achieve the partial updating effect.

OK, that is all for this part. In the next part, we will start with the detailed programming.

Downloads
Conclusion

In this article, we have first introduced the two famous Ajax frameworks, Prototype and script.aculo.us, because of their important positions in the web tag system. In fact, for brevity, we have only showed you their parts of Ajax related functionalities with related examples.

Next, we introduced the general system requirements of the web tag system to develop. In fact, as you have imaged, a web tag application holds only a few functions. So, there are merely two tables designed in the system. As a typical three-tiered application, we selected to leverage stored procedures to encapsulate the data in the tables, as well as Microsoft SqlHelper class to simplify the data access operations. In the second section, we will start to write the web tag application in details.



©Copyright 1998-2020 ASPAlliance.com  |  Page Processed at 2020-08-03 10:26:36 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search