Chat Application in ASP.NET Using AJAX (Pop-up Windows)






4.83/5 (26 votes)
Chat application in ASP.NET using AJAX and SQL Server.
Introduction
In this post, I want to share my work on developing a chat application that can be used with your regular ASP.NET applications. I am using AJAX, and SQL Server for the backend. This can only be used in ASP.NET 2.0 or higher as I am using the UpdatePanel
.
Using the code
The application works as follows:
- List of online users are displayed.
- The current logged-in user will click on a user name to open a new chat window, and types a message.
Online users list can be loaded from the backend database, logging an entry when a user logs into the application. The user names will be displayed as hyperlinks, with a unique chat ID for each.
On clicking a username, the OpenChatBox()
function is called with the chat ID as the parameter. When the user types any message and clicks on the Send button, the message is sent to the server and stored to the database with the chat ID supplied.
function OpenChatBox(uid, chatid) {
var win = window.open("ChatBox.aspx?uid=" + uid + "&cid=" +
chatid, "ChatWindow" + chatid +
document.getElementById('hidCurrentUser').value,
"status=0,toolbar=0, menubar=0, width=450, height=550");
top = top + 50;
if (top > screen.availHeight - 550)
top = 100;
left = left + 50;
if (left > screen.availWidth - 450)
left = 100;
win.moveTo(left, top);
chats[chats.length] = win;
return false;
}
The message storing is implemented in ASP.NET.
Private Sub SendMessage(ByVal msg As String)
Dim con As SqlConnection = New SqlConnection( _
"Data Source=.\SQLEXPRESS;AttachDbFilename=" & _
"D:\Dev\Projects\WebChat\WebChat\App_Data\WebChat" & _
".mdf;Integrated Security=True;User Instance=True")
con.Open()
Dim comm As SqlCommand = New SqlCommand("stp_SendMessage", con)
comm.CommandType = CommandType.StoredProcedure
Dim paramSender As SqlParameter = New SqlParameter( _
"@Sender", SqlDbType.VarChar, 10)
paramSender.Value = HttpContext.Current.User.Identity.Name
comm.Parameters.Add(paramSender)
Dim paramRec As SqlParameter = New SqlParameter( _
"@Reciever", SqlDbType.VarChar, 10)
paramRec.Value = ViewState("uid")
comm.Parameters.Add(paramRec)
Dim paramMsg As SqlParameter = New SqlParameter( _
"@Msg", SqlDbType.VarChar, 1000)
paramMsg.Value = msg
comm.Parameters.Add(paramMsg)
'store the chat id supplied from browser
Dim paramChatId As SqlParameter = New SqlParameter( _
"@ChatId", SqlDbType.VarChar, 100)
paramChatId.Value = ViewState("vwChatId").ToString()
comm.Parameters.Add(paramChatId)
comm.ExecuteNonQuery()
con.Close()
End Sub
One every user's home page, a script is run every 5 seconds to ping the server for any messages.
function PingServer() {
PingServerForMsg()
setTimeout(PingServer, 5000);
}
function PingServerForMsg() {
// Use ajax to call the GetChatMsg.aspx to get any new messages.
xmlHttp = GetXmlHttpObject(stateChangeHandler);
}
This JavaScript message will call the GetChatMsg.aspx page for new messages, and shown below is the code for GetChatMsg.aspx:
Imports System.Data
Imports System.Data.SqlClient
Partial Public Class GetChatMsg
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Response.Clear()
Response.ClearContent()
'set response to not to cache, to avoid the ajax from displaying old message.
Response.AddHeader("Cache-Control", "no-cache, must-revalidate")
Dim ds As DataSet = GetMessage(HttpContext.Current.User.Identity.Name)
Dim strMsg As String = ""
If ds.Tables.Count > 0 Then
If ds.Tables(0).Rows.Count > 0 Then
For Each dr As DataRow In ds.Tables(0).Rows
If strMsg.Length > 0 Then
strMsg += "#"
End If
strMsg += dr("Sender").ToString() + "&"
strMsg += dr("ChatId").ToString() + "&"
strMsg += dr("Msg").ToString().Replace("&", _
"_@AMP__").Replace("#", "_@HASH__")
Next
End If
End If
Response.Write(strMsg)
Response.End()
End Sub
Private Function GetMessage(ByVal strUid As String) As DataSet
Dim dsMsgs As DataSet = New DataSet()
Dim con As SqlConnection = New SqlConnection( _
"Data Source=.\SQLEXPRESS;AttachDbFilename=D:\Dev\" & _
"Projects\WebChat\WebChat\App_Data\WebChat.mdf;" & _
"Integrated Security=True;User Instance=True")
con.Open()
Dim comm As SqlCommand = New SqlCommand("stp_GetMessage", con)
comm.CommandType = CommandType.StoredProcedure
Dim paramSender As SqlParameter = New SqlParameter( _
"@Uid", SqlDbType.VarChar, 10)
paramSender.Value = HttpContext.Current.User.Identity.Name
comm.Parameters.Add(paramSender)
If (Request.QueryString("cid") <> Nothing) Then
Dim paramChatId As SqlParameter = New SqlParameter( _
"@ChatId", SqlDbType.VarChar, 100)
paramChatId.Value = Request.QueryString("cid")
comm.Parameters.Add(paramChatId)
End If
Dim da As SqlDataAdapter = New SqlDataAdapter(comm)
da.Fill(dsMsgs)
con.Close()
Return dsMsgs
End Function
End Class
On the browser side, on getting a new message, the browser will open a pop-up if the chat ID is new, or will show the message if a pop-up is already open for the chat ID associated with the new message.
function stateChangeHandler() {
//readyState of 4 or 'complete' represents that data has been returned
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 'complete') {
//Gather the results from the callback
var str = xmlHttp.responseText;
if (str != "" ) {
//document.getElementById('txtMsg').value = str;
//eval(str);
var msgs = str.split('#');
for (ind = 0; ind < msgs.length; ind++) {
msgs[ind] = msgs[ind].replace("_@HASH__", "#");
var msg = msgs[ind].split("&");
msg[0] = msg[0].replace("_@AMP__", "&");
msg[1] = msg[1].replace("_@AMP__", "&");
msg[2] = msg[2].replace("_@AMP__", "&");
var blnExisting = false;
for (iind = 0; iind < chats.length; iind++) {
try
{
if (chats[iind] != null && chats[iind].name ==
"ChatWindow" + msg[1] +
document.getElementById('hidCurrentUser').value)
blnExisting = true;
}
catch(e){}
}
if( blnExisting == false)
OpenChatBox(msg[0], msg[1]);
}
}
}
}
The recipient can type in a message to reply back using the same window. The pop-up window has the screen ChatBox.aspx, which has the ChatBox.js reference of the JavaScript code to ping the server again every second. But this time, it uses the chat ID assigned to that window. And thus, every chat has a unique chat ID, and chat messages are maintained at the backend by the chat ID, and the pop-up windows communicate through the chat ID. An UpdatePanel
is used here to avoid flickering of the chat window when the user clicks Send Message. And when a message is received by the recipient, the message is deleted at the server.
A user can chat with any number of users as pop-up windows are used for each chat with a unique chat ID for the chat. The chat ID is generated as 'Timestamp + Sender ID + Recipient ID'.
On clicking the Send button, the typed message will be saved by the code-behind to a table in SQL Server (here, any other database can be used). On the recipient side, on AJAX call, the message reader will read the messages related to the recipient and sent to the recipient. Please check the attached source code for the ASP.NET code, which is for Visual Studio 2008, but the same code can be used for VS 2005 (ASP.NET 2.0) without changes.
When the first user sends a message, the message is saved to the backend for the selected user. When the application running on the recipient (implemented in default.aspx in the sample), AJAX is used to ping the server for messages every 5 seconds.
Enhancements
- Developers can try to implement saving the chat history.
- The list of online users can be implemented in a user control to make it reusable.
- Chat window can be changed to include the time of message and images.