Building an AJAX Based Web Chatting Application using ASP.NET 2.0(转载)

  • Download AjaxProChat - 503.27 KB

Introduction

This article will present you with a Web chatting application, which is based on the famous open source AjaxPro.NET library. Here, we will establish ourselves a nice little multi-user chat application, much like the famous MSN Messenger. We will build the application heavily on JavaScript programming (which is decided by the AjaxPro.NET Framework which supports accessing .NET library through the client-side JavaScript way) under ASP.NET 2.0 and SQL Server Express Edition environments.

Testing Environment

  • Windows XP Professional (with IIS installed)
  • Visual Studio 2005 (plus SQL Server 2005 Express Edition)
  • AjaxPro.NET Framework

Also, you are to be familiar with ASP.NET 2.0 C# programming, SQL Server programming and JavaScript+ DOM. To follow along with the examples, you should download the source files accompanying this article (see the download URL given at the end of the article).

The sample project named AjaxProChat in this article will achieve the listed basic goals.

  • View the on-line chatting friends in real-time
  • Send instantaneous messages to the on-line friends
  • Receive messages in real-time and pop up a friendly MSN-like hint window
  • Switch between the different states—online and offline

Thus, we can easily describe the general flow chart of this chatting application, as shown in Figure 1.

Figure 1

No doubt that the key lies in the real-time features—state switching in real-time, sending and receiving messages instantaneously, etc. There are many difficulties in tackling all these merely with the traditional web techniques, but now AJAX comes to rescue— all the troubles can be whiled away. Let us now roll up our sleeves by beginning with the database design.

Database Design

With the general goals introduced above, we can now shift our attention to the database design.

In this case, we will design a database named AjaxProChat, which contains three tables—users for holding users info, message for the detailed chatting info, and global_info for recording the changing times in tableusers.

Designing the Tables

Since the source code file with this article provides a whole database, I will omit the relevant creating-table SQL scripts. So, let us directly delve into the table structures. The following three tables give their corresponding structure definitions and field notes, respectively.

Table 1: Structure for Table Users

Field name Type Notes
username varchar(50) NOT NULL, Primary KeyThe login user name
nickname varchar(50) Can be nullThe nickname associated with the user name defined above
password varchar(50) NOT NULL
status int NOT NULL, DEFAULT (0)The user login status—0: offline; 1: online; 2: hidden
logintime datetime Can be NULLThe datetime of the user logging in the last time
logouttime datetime Can be NULLThe datetime of the user logging out the last time
last_msg_id int NOT NULL, DEFAULT (0)The last received message id of the user

Table 2: Structure for Table Message

Field name Type Notes
msg_id int IDENTITY (1,1) NOT NULL, Primary KeyThe auto incremental message id
sender varchar(50) NOT NULLThe user name of the sender
receiver varchar(50) NOT NULLThe user name of the receiver
content varchar(255) NOT NULLThe corresponding chatting content
sendtime datetime NOT NULLThe datetime of sending the message

Table 3: Structure for Table global_info

Field name Type Notes
UserChanged int NOT NULL, DEFAULT (0)

Besides these tables, we have also defined a trigger in table users. This means that whenever there are appending, deleting or updating with the records in it, the trigger should be invoked to add 1 to the fieldUserChanged in table global_info.

Designing the Stored Procedures

To improve the efficiency and simplify the database access, we design five stored procedures inside databaseAjaxProChat. Below we enumerate them and their corresponding functions:

  • GetNewMessage—Fetch the most recent messages which accord with specified conditions
  • GetRecentMsg—Return the chatting info of the two specified most recent users
  • SendMessage—Save the sent messages (the sent and received ones) as new records into the database
  • UserLogin—Log into the system—return zero if successful, otherwise return 1
  • UserLogout—Perform the inverse action of UserLogin

Since you will begin a long journey and I have provided the commented source code for you to download, we will not list their SQL scripts herein any more. But with the story going on, you will quickly conclude that nearly all the .aspx pages are filled with the following call route as depicted in Figure 2.

 

Building an AJAX Based Web Chatting Application using ASP.NET 2.0(转载)_第1张图片Figure 2

Detailing the Solution

Before starting to put AjaxPro.NET into action, let me give you a brief introduction.

AjaxPro.NET is a well-known open source framework, which is based on the server-side techniques and provides support for constructing different versions of .NET Web applications. The framework supports the server-side .NET SDK by a few means via the client-side JavaScript. It can direct the JavaScript requests to the related server-side .NET methods and then the server returns the newly-generated special JavaScript to the browser. Its main functions are listed as below:

  • Access the Session and Application data from the client-side JavaScript
  • Cache the required results
  • Freely use source code
  • Add and modify new methods and properties in the framework without modifying any source code
  • All the classes support the client-side JavaScript to return data, and DataSet can be used from inside the JavaScript
  • Use the HTML controls to access and return data
  • Do not need reload the pages and use the event delegate to access data n
  • Supply only one method for call and dramatically decrease the CPU usage

Now, to use AjaxPro.NET in our ASP.NET 2.0 web applications we should properly configure the web.configfile. Since the downloaded materials have been shipped with a guide and an excellent Visual Studio Add-in—AjaxProVSTemplate.vsi, we will not talk much about the usage of this framework, but focus on the main topic.

In this demo application we mainly provide three web pages—login.aspx, main.aspx, and chatroom.aspx. There is, however, a small trick worthy to be mentioned first.

Index.html—a broker

To hide the browser's menu bar and toolbars in our chatting pages, we use some tricks -building a temporary broker page index.html. The client-side JavaScript in Listing 1 below shows the how-to.

Listing 1

Collapse Copy Code
");
        //merely for debugging purpose
    }
    finally
    {
      sqlConnection.Close();
    }
    if (iRet == 0)
    {
      FormsAuthentication.RedirectFromLoginPage(tbUsername.Text, false);
      Response.Redirect("Main.aspx");
    }
    if (iRet == 2)
    {
      FormsAuthentication.RedirectFromLoginPage(tbUsername.Text, false);
      Response.Redirect("Main.aspx");
    }
    else
    {
      lblMessage.Text = "iRet =" + iRet.ToString() +
        "The login failed, please check out your password!";
    }
  }
}

Main.aspx—The Headquarters

Now, let us pay attention to the main controlling page of the chatting system, main.aspx, whose run-time snapshot is shown in Figure 4.

 

Building an AJAX Based Web Chatting Application using ASP.NET 2.0(转载)_第2张图片Figure 4

From the developer's point view, we can divide this part into three different components: login status switching, the users list viewing, and the newest message hinting. So, let us dig into their inner workings one by one.

Switching Between the Login States

At the top of the main page lie the current user name and its login status. It is easy for the user to switch between items Online and Offline via the ListBox control. When the user click the Logout button, the user will log off and the control is switched to the initial login page. Now, let us examine the related inner logic. First, we define an Ajax method—SetUserStatus on the server side, which directly updates the user login status in table users according to the passed arguments—strUsername and iStatus. Listing 3 gives the corresponding coding:

Listing 3

Collapse Copy Code
[AjaxPro.AjaxMethod]
public  int SetUserStatus(string strUsername, int iStatus) {
     //hold the returned value
      int iRet = 0;
     //Obtain the database connection string from the file web.config and set up the connection
      string strConnection = ConfigurationManager.ConnectionStrings["msn_Data_ConnStr"].ConnectionString;
      SqlConnection conn = new SqlConnection(strConnection);
 
     //create a new SQLCommand object
      SqlCommand cmd = conn.CreateCommand();
      cmd.CommandText = string.Format(
            "UPDATE users SET status = {0} WHERE username='{1}'",
            iStatus, strUsername
            );
      try{
           //open the data connection
            conn.Open();
           //execute the SQL command-- set the user's status
            iRet = cmd.ExecuteNonQuery();
      }
      catch (SqlException){}
      finally
      {
           //close the database connection
            conn.Close();
      }
      return iRet;
}

Next comes up the relevant client-side function, setUserStatus, which will call the server-side methodsetUserStatus to update the current user login status, as is shown in Listing 4.

Listing 4: The Client-Side JavaScript Method Calls the Server-Side Ajax One

Collapse Copy Code
 Collapse Copy Codefunction setUserStatus()
{
      //user name
      var username = el("lblUsername").innerText;
      //status
      var status = el("user_status").value;
      //call the relevant server-side Ajax method
      AjaxProChat.SetUserStatus(username, status);
}

As for logoff, this is performed inside the button Logout-related event handler, lblExit_Click, via the routine ASP.NET event response mechanism. Here we leave out the code listing.

Viewing the User List

Note that, in this case, we take the action of inquiring the database on time to list all the on-line users stuff. Therefore, we have to earnestly count the cost between the user real-time characteristics and the server-side load. Obviously, if the interval for inquiring the database is shorter, then the real-time features of the application will be acceptable, which will put a heavier burden on the server's shoulder. However, if the interval is longer, then there is a lighter load on the server and the merciful real-time characteristics on the client side. So, here we use some sleight: in the database we add a sign—the field UsersChanged in the tableglobal_info which is used to record the times table users to be changed. So, in the code we can judge on time whether the sign has been changed to decide whether to send requests to the server side for updating the on-line users list or not. Here, for brevity, we select to omit the simple server-side code while making room for the client-side programming.

Listing 5

Collapse Copy Code
 Collapse Copy Code//update the users list
function refreshUserlist()
{
 //get the value of field UsersChanged from inside table users on the server side
  var changed = AjaxProChat.StatusChanged().value;
 //if table users has changed
  if (changed > changedTimes)
  {
   //write down the current value of field UsersChanged
    changedTimes = changed;
   //obtain the DataTable object to hold the users info
    var arUserlist = AjaxProChat.GetOnlineUserList().value.Tables[0];
   //the 
object to show the users list var divUserlist = el("userlist"); //remove the old contents while (divUserlist.childNodes.length > 0) { divUserlist.removeChild(divUserlist.childNodes[0]); } //show the users list for (var i = 0; i < arUserlist.Rows.length; i++) { //the login user name var username = arUserlist.Rows[i].username; //nickname var nickname = arUserlist.Rows[i].nickname; //create a
object for showing one user message var result = document.createElement("div"); //set the cursor shape hand-like result.style.cursor = "pointer"; //inner patches result.style.padding = "2px 0px 2px 0px"; //mouse click handler--open the chat room window result.onclick = function() { //if the chat room window has not been opened if (!sendWindow) { // open the chat room window--note the passed parameters window.showModelessDialog("chatroom.aspx?username=" + username, window, "help:no;unadorned:yes;edge:sunken;resizable:yes;status:no") ; } }; //the texts for the user name and the nickname are to be shown inside the object var result1 = document.createElement("span"); //set the mouse in-and-out effect result1.onmouseover = function() { this.style.color = "#205288"; }; result1.onmouseout = function() { this.style.color = "#000000"; }; //set show style result1.style.textAlign = "left"; result1.style.fontWeight = "bold"; result1.style.fontFamily = "Arial, Verdana"; //show the user name plus the nickname result1.innerHTML = username + " (" + nickname + ")"; //attach the
object to DOM result.appendChild(result1); divUserlist.appendChild(result); } } }

Since we have added so many comments on the import line, we only sum up the general process: obtain the most recent users list inside the database via the Ajax method—AjaxProChat.GetOnlineUserList(); fill in the user name and related nickname in turn. As is seen from above, we use much subtle JavaScript programming around the DOM object—div and span.

A MSN-like Popping up Window

TBuilding an AJAX Based Web Chatting Application using ASP.NET 2.0(转载)_第3张图片o conveniently accept the new messages, we have designed a small and friendly MSN-like hint window.

Figure 5: The run-time screenshot of the MSN-like hint window

Page main.aspx is responsible for checking on time whether there have been new messages coming in; if so, this small hint window is to be popped up and the current user can click the link in it to reply. As with the functions of the main page, there are also two steps—both the server side and the client side—needed to accomplish such a prompt action. First, we have defined an Ajax method, mainGetNewMessage, who serves to obtain a DataSet of the newest chatting messages. We can see the typical database connection in ASP.NET 2.0 from Listing 6.

Listing 6: Code for the Server-Side Method mainGetNewMessage

Collapse Copy Code
 Collapse Copy Code[AjaxPro.AjaxMethod]
public DataSet mainGetNewMessage()
{
  DataSet ds = new DataSet();
  SqlConnection conn = new SqlConnection
    (ConfigurationManager.ConnectionStrings["msn_Data_ConnStr"].ConnectionString);
  SqlCommand cmd = conn.CreateCommand();
  cmd.CommandText = string.Format("GetNewMessage '{0}'", User.Identity.Name);
  SqlDataAdapter da = new SqlDataAdapter(cmd);
  try
  {
    da.Fill(ds);
  }
  catch (SqlException){}
  finally
  {
    conn.Close();
  }
  return ds;
}

Since the code above is the common database operation and is provided with so many notations, we will not give unnecessary details any more.

On the client side, there is accordingly defined a method, checkNewMessage, who is to invoke the server-side method, mainGetNewMessage, and will pop up a hint box whenever there comes a new message. Listing 7 shows the related code snippet.

Listing 7: Code for the Client-Side Method checkNewMessage

Collapse Copy Code
 Collapse Copy Codefunction checkNewMessage()
{
  if (!sendWindow)
  {
    var dt = AjaxProChat.mainGetNewMessage().value.Tables[0];
    if (dt.Rows.length > 0)
    {
      var sender = dt.Rows[0].sender;
      var content = DealBrackets(dt.Rows[0].content);
      var MSG1 = new CLASS_MSN_MESSAGE("aa", 200, 120, "Hint:", sender +
        " says: ", content);
      MSG1.oncommand = function()
      {
        if (!sendWindow)
        {
          window.showModelessDialog("chatroom.aspx?username=" + sender, window,
            "help:no;unadorned:yes;edge:sunken;status:no");
        }
      };
      MSG1.rect(null, null, null, screen.height - 50);
      MSG1.speed = 10;
      MSG1.step = 5;
      MSG1.show();
    }
  }
}

Here shows the typical flow of calling an Ajax method on the server side from within JavaScript on the client side. As you may have guessed, the true secret for this hint window lies in the following code snippet.

Listing 8

Collapse Copy Code
Collapse Copy Codevar MSG1 = new CLASS_MSN_MESSAGE("aa",200,120,"Hint:",sender + " says: ",content);

Inside the downloadable source code, we define a pop up window class in JavaScript in the fileCLASS_MSN_MESSAGE.js. We are creating an instance of the class CLASS_MSN_MESSAGE and the last line above show the pop up window by calling the show method of the instance. For more details please do research into the relevant JavaScript coding.

Chatroom.aspx

Lastly, we come to the meat and potatoes of this Ajax-based chatting application. The really important window to start chatting is page chatroom.aspx. Let us first look at its run-time screenshot in Figure 6.

Figure 6

As is seen from Figure 6, it is rather simple. Most of the page is for chatting with friends and the corresponding messages, with a TEXTBOX control for entering the message to send and a basic Send button at the bottom line. You may have already guessed the similar JavaScript programming skill is used for arranging the

object and its inner sub items.

For easier comprehension, we have also divided the part into three components: examining the recent messages, sending the messages, and receiving the messages. Again, let us analyze them one after the other.

Examining the recent messages

When the chat room window is loaded, there is a specified number of latest chatting messages to be loaded. For this purpose, an AJAX method—GetRecentMsg is defined on the server side which then invokes the stored procedure GetRecentMsg and finally the required items of chat records return. Listing 9 gives the specific coding of method GetRecentMsg.

Listing 9

Collapse Copy Code
 Collapse Copy Code[AjaxPro.AjaxMethod]
public DataSet GetRecentMsg(string strUsername)
{
  DataSet ds = new DataSet();
  SqlConnection conn = new SqlConnection
    (ConfigurationManager.ConnectionStrings["msn_Data_ConnStr"].ConnectionString);
  SqlCommand cmd = conn.CreateCommand();
  cmd.CommandText = string.Format("GetRecentMsg '{0}','{1}', {2}",
    User.Identity.Name, strUsername, 8);
  SqlDataAdapter da = new SqlDataAdapter(cmd);
 
  try
  {
    da.Fill(ds);
  }
  catch (SqlException){}
  finally
  {
    conn.Close();
  }
  return ds;
}

Sending the messages

For this purpose, an AJAX method—SendMessage is defined on the server side which then invokes the stored procedure GetRecentMsg and finally the required items of chat records return. Listing 10 gives the specific coding of method GetRecentMsg.

Listing 10

Collapse Copy Code
 Collapse Copy Code[AjaxPro.AjaxMethod]
public DataSet GetRecentMsg(string strUsername)
{
  DataSet ds = new DataSet();
  SqlConnection conn = new SqlConnection
    (ConfigurationManager.ConnectionStrings["msn_Data_ConnStr"].ConnectionString);
  SqlCommand cmd = conn.CreateCommand();
  cmd.CommandText = string.Format("GetRecentMsg '{0}','{1}', {2}",
    User.Identity.Name, strUsername, 8);
  SqlDataAdapter da = new SqlDataAdapter(cmd);
  try
  {
    da.Fill(ds);
  }
  catch (SqlException){}
  finally
  {
    conn.Close();
  }
  return ds;
}

Receiving the messages

Here, certainly should we receive the messages in real time, while the whole process is very much similar to that of the main page, so we do not say more than is needed. But there is still one thing to be noticed, if the chat room window has been open, the new message will be shown directly in it; otherwise there will pop up a small hinting window (see Figure 5) for this new message. This is why the global variable sendWindow is defined inside page main.aspx's client-side JavaScript, as is shown below.

Listing 11: The initial definition of the variable sendWindow

Collapse Copy Code
 Collapse Copy Code//……(omitted, inside main.aspx)

                    
                    

你可能感兴趣的:(Building an AJAX Based Web Chatting Application using ASP.NET 2.0(转载))