Introduction
This article describes how to implement a web-chat with ASP.NET and Ajax. In the first part I introduce the technologies I used for the application. Then I explain the concept of a chat and in the last part I present the main implementations. The goal of this article is to show the interested reader how to develop a chat without browser-plugins or java-applets, just pure HTML and JavaScript.
Which Technology is Used?
A web-chat is an application for which dynamically generated HTML is needed and client-server interaction. Therefore, ASP.NET 2.0 has been used and of course Ajax for the client-server-intercation without postbacks. We could use Ajax.NET but to keep it simple we decided to use the Ajax-implementation from Mike Schwartz called AjaxPro.
To do all serverside calls from JavaScript with AjaxPro you need to do the following:
- Add a reference to the Assembly AjaxPro.dll from Mike Schwartz.
- Add a class to your project.
- Add a method to that class you want to call by script and mark it with the Attribute AjaxMethod
- Register the class in the Page_Load-handler of your aspx-page from which you want to use it. With
AjaxPro.Utility.RegisterTypeForAjax(typeof(MyAjaxClass));
That's all. Other details will be explained in the implemenation-part of the article.
The Design of a Chat?
There are different kind of chats. In this example I designed a chat in which users can login with their username and password. Then they can enter the chat and send messages. The messages are visible for all other chat-users. It is a public chat, where all logged in chatters can communicate together.
The Session holds a CurrentChatter
, a user that has just logged in. The chatter enters the chat (1) by navigating to the chat-page (Chat.aspx). After a chatter has entered, he has the possibility to send messages by typing text to a TextBox and pressing the enter-key. Then the chat-message is sent to a ChatMessageQueue
(CMQ) which in our example is stored in the Application (2). Okay, now the message lies in the CMQ on the server. We have to get it from there, so that every client can see it. Therefore we have a JavaScript-timer running, that gets all new messages from the CMQ and displays it in an HTML-DIV for example (3). Sounds simple, doesn't it? Here is what we need to do, to implement points 1 to 3.
(1) AddChatter (store chat-user)
Save the curent user after successful login to the Session.
(2) AddToMsgQueue
When sending a chat-message you need to store this in the CMQ. You will have to invoke this action from a JavaScript function. The scriptcode calls a serverside method via Ajax that has the ability to access the ASP.NET-Application.
(3) GetMsgsFromQueue
Here we need to check in a JavaScript-timer every n seconds, if there are new chat-messages for the client to display. So we poll the CMQ for new messages by an Ajax-method. If we have new messages, these are transformed to a string that can be displayed as a list in a chatwindow.
The Implementation
So far the theory, now the concrete coding. Here are the datatypes we need
Chatter
This class has an Id to identify a chatter internally and a name for the display. The LastMsgKey
is the key of the last message a chatter received. When the timer polls for new messages, this key is used to find out, if there are messages in the CMQ after that message. The messages are stored in a list in the application. If there are messages in the list for the chatter after his LastMsgKey
, these messages have to be fetched.
ChatMsg
A chat-message has a Key (Guid), the name of the chatter who sent this message and the message itself as string.
ChatMgr
The ChatMgr
handles the list of all logged in chatters and the CMQ. You can add messages to the CMQ and get them back from it. It also has methods to get a list of all available chatters as HTML. The code could be optimized here: The display-logic for chatters and chat-messages could be placed to another class.
The HTML-components are located on the WebForm Chat.aspx. We have
- divChatBox: A DIV for all chatmessages.
- divChatters: A DIV for all logged in chatters
- txtMessage: A TextArea for the text that a chatter can type and send.
When the page loads, all logged in chatters and the available messages are loaded and displayed in the corresponding HTML-elements. Here is the JavaScript-code which is called cause we add the calls to it in the onload-handler of the Chat.aspx-page:
function fillUsers()
{
ChatMgr.GetChattersHtml( fillUsers_CallBack );
}
function fillUsers_CallBack( res )
{
var userBox = document.getElementById('divUsers');
if( res.value == '' )
{
setTimeout( "fillUsers()", 5000 );
return;
}
userBox.innerHTML = res.value;
setTimeout( "fillUsers()", 5000 );
}
function getMsgs()
{
ChatMgr.GetMsgsFromQueue( getMsgs_CallBack );
}
function getMsgs_CallBack( res )
{
var chatBox = document.getElementById('divChatBox');
chatBox.innerHTML += res.value;
scrollContentDown();
setTimeout( "getMsgs()", 2000 );
}
The _callback
-functions are asynchronous callbacks. They are initiated by the Ajax-calls of the ChatMgr
. In the end of a _callback
-function setTimeout
is called to invoke the function again after a certain period. Now how is the ChatMgr
able to call a serverside function from script? See the example of the call GetChattersHtml
[ AjaxMethod( HttpSessionStateRequirement.Read ) ]
public string GetChattersHtml()
{
string result = "";
if( SessionMgr.Instance.OnlineUsers == null )
return result;
foreach (Member member in SessionMgr.Instance.OnlineUsers.Values )
{
result += "<div class='ChatUser' style='width: 280px'>";
result += "<table border=0 cellpadding=0 cellspacing=0><tr>";
result += "<td>" + UserImage.GetHtml( member.ID, "" ) + "</td>";
result += "<td> <b>" + member.Name + "</b></td>";
result += "</tr></table>";
result += "</div>";
}
return result;
}
The method of the ChatMgr
is marked with the attribute AjaxMethod
. To get access to the current Session, we add the HttpSessionStateRequirement.Read
to that attribute. Now the method can read all logged in users from the session and give back the list as HTML. If we also want to be able to write to the HttpSession we could use HttpSessionStateRequirement.ReadWrite
.
For the other code-parts it's just the same: the script calls the serverside method, the method returns the return-values which are read-out in an asynchronous callback-function in script.
Here is the logic for sending messages to the queue:
function sendMessage()
{
var newMsg = '';
var chatBox = null;
var msg = document.getElementById('txtMsg').value;
if( msg == '' )
return;
document.getElementById('txtMsg').value = '';
newMsg = ChatMgr.AddToMsgQueue( msg ).value;
chatBox = document.getElementById('divChatBox');
chatBox.innerHTML += '' +
newMsg.Name + ': ' + newMsg.Message + '';
}
On pressing return, the function sendMessage
is called and adds the message to the CMQ by calling the method AddToMsgQueue
of the ChatMgr
which again is an Ajax-method. If you have further questions on how to build an ASP.NET-Ajax-Chat or want codegod to implement it for you, just send us a mail.
You can see the codegod-chat in action here after logging in. For more information on ASP.NET and Ajax visit our page here