Introduction
This is a simple AJAX based chat done in C#.
Instructions
Important note: This is a chat made for ASP.NET 2.0 (VS2005 or later).
- Add a new web form to your solution, name it ChatPage.aspx, choose C# language.
- Copy and paste the page HTML to the source view of your web form.
- Copy and paste the page code-behind to the code-behind file of your web form named ChatPage.aspx.cs.
- Copy and paste the Business logic to a new class in your App_Code folder named SPilafisChatLogic.cs.
- Add AJAX for ASP.NET 2.0 (VS2005) to your solution. (With VS2005, you just have to drag and drop the DLL in your bin folder and add a couple of lines to your web.config.)
- Get some french fries and enjoy!
Page HTML
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="ChatPage.aspx.cs" Inherits="ChatPage" %>
<!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" xml:lang="en" >
<head id="Head1" runat="server">
<title>Chat Ajax .NET</title>
<style type="text/css">
td {
font-family: Arial;
font-size: 8pt;
}
</style>
</head>
<body>
<form id="form1" runat="server" onsubmit="return false;">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<table align="center" width="732"
border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<textarea id="txtChatFrame" runat="server"
rows="15"
style="width:527px; border:1px solid #aaaaaa; padding:4px;"
readonly="readonly"></textarea><br/>
</td>
<td valign="top">
<div style="overflow: auto; height: 226px; border-top:
solid 2px gray; border-bottom: solid 2px gray;
border-right: solid 1px gray; border-left: solid 1px gray; ">
<asp:GridView ID="grvUsers" runat="server"
AutoGenerateColumns="False" BackColor="White"
BorderColor="#DEDFDE" BorderStyle="None"
BorderWidth="1px" CellPadding="1"
ForeColor="Black"
GridLines="Vertical" Height="30px">
<FooterStyle BackColor="#CCCC99" />
<Columns>
<asp:BoundField HeaderText="User"
ReadOnly="True" DataField="ChatUsers">
<ItemStyle Width="110px" />
<HeaderStyle Height="10px" />
</asp:BoundField>
<asp:BoundField HeaderText="Last Activity"
DataField="ChatLastActivity">
<ItemStyle Width="190px" />
<HeaderStyle Height="10px" />
</asp:BoundField>
</Columns>
<RowStyle BackColor="#F7F7DE" />
<SelectedRowStyle BackColor="#CE5D5A"
Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#F7F7DE"
ForeColor="Black" HorizontalAlign="Right" />
<HeaderStyle BackColor="#6B696B"
Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
</asp:GridView>
</div>
<input id="btnRefresh" runat="server"
type="submit" onclick="document.forms['form1'].submit();"
value="Refresh"
style="cursor:pointer;border:1px solid gray; height: 15px;
width: 100%; font-size: 7pt;"
size="20"/>
</td>
</tr>
<tr>
<td>
<table border="0" cellpadding="0"
cellspacing="5" style="width:527px;">
<tr>
<td align="right" valign="middle">Message: </td>
<td align="left" style="height: 45px" valign="top">
<table border="0" cellpadding="0" cellspacing="2">
<tr>
<td><textarea cols="70" rows="2"
id="txtMssg"
style="border:1px solid gray; width: 370px; height: 37px;"
onkeyup="SendByKey(event.keyCode);"></textarea></td>
<td><input id="btnSend" type="button"
value="Send" onclick="Send()"
style="cursor:pointer;border:1px solid gray;
height: 42px;"/></td>
</tr>
</table></td>
</tr>
<tr>
<td align="right" valign="middle"
style="width:70px">User Name: </td>
<td align="left">
<table border="0"
cellpadding="0" cellspacing="2">
<tr>
<td><input id="txtName" type="text"
maxlength="10"
style="border:1px solid #aaaaaa; width: 145px;"
onblur="ChangeUserName(this);"/
value="<%=SpilafisChatLogic.Chat.GetUserName()%>" />
</td>
<td>
Get source code!:
<a href="http://www.spilafis.com.ar">
http://www.spilafis.com.ar</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
<td valign="middle">
<br />
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td align="center">Users Writing: <br />
(max. <%=SpilafisChatLogic.Chat.MaxLoggedInUsers.ToString()%>)
</td>
<td align="right"><span id="spnW">0</span> <br /><br /></td>
</tr>
<tr>
<td colspan="2"> <br /></td>
</tr>
<tr>
<td align="left">Users Reading: </td>
<td align="right"><span id="spnR">0</span></td>
</tr>
</table>
</td>
</tr>
</table>
<br />
<br />
<script type="text/javascript" language="javascript">
function ChangeUserName(otxtName)
{
var tentative_name = otxtName.value;
if(tentative_name=="")
alert("You must enter a user name to be able to chat.");
else
{
if(tentative_name!=last_user_name)
{
var otxtMssg = document.getElementById("txtMssg");
var obtnSend = document.getElementById("btnSend");
var ret = Chat.ChangeUserName(tentative_name);
if(ret!=null && ret.error!=null && ret.error!="")
{
otxtName.value = last_user_name;
alert(new String(ret.error).replace("System.Exception ",""));
}
else
{
last_user_name = otxtName.value;
obtnSend.disabled = false;
otxtMssg.disabled = false;
otxtMssg.focus();
}
}
}
}
function Send()
{
var otxtName = document.getElementById("txtName");
if(otxtName.value!="")
{
var otxtMssg = document.getElementById("txtMssg");
if(!otxtMssg.disabled)
{
var ret = Chat.Post(otxtMssg.value);
if(ret!=null && ret.error!=null)
{
alert(new String(ret.error).replace("System.Exception ",""));
}
otxtMssg.value = "";
otxtMssg.focus();
}
}
else
{
if(!otxtName.disabled)
{
alert("Enter a user name");
otxtName.focus();
}
}
}
function SendByKey(keycode)
{
if (keycode == 13)
Send();
event.returnValue = false;
}
var cycles = 20;
var add_wait_cycles = 20;
var reload_wait = 700;
var last_user_name = "";
var max_chat_lines = <%=SpilafisChatLogic.Chat.MaxChatLines%>;
function Reload()
{
var ret;
cycles++;;
if(cycles>=add_wait_cycles)
{
cycles = 0;
// Get users writing
ret = Chat.GetUsersWriting();
if(ret!=null && (ret.error==null || ret.error=="") &&
ret.value!=null && ret.value!="")
document.getElementById("spnW").innerHTML = ret.value;
// Get users reading
ret = Chat.GetUsersReading();
if(ret!=null && (ret.error==null || ret.error=="") &&
ret.value!=null && ret.value!="")
document.getElementById("spnR").innerHTML = ret.value;
}
// If not logged in to write then try to logg in the user
var otxtMssg = document.getElementById("txtMssg");
if(otxtMssg.disabled)
{
var otxtName = document.getElementById("txtName");
if(otxtName.value=="")
{
ret = Chat.GetNextUserName();
if(ret!=null && ret.error==null &&
ret.value!=null && ret.value!="")
{
otxtName.value = ret.value;
LoggedIn();
alert("You have been logged in");
}
}
else
{
last_user_name = otxtName.value;
otxtMssg.disabled = false;
var obtnSend = document.getElementById("obtnSend");
obtnSend.disabled = false;
otxtMssg.focus();
}
}
// Read Chat
var ret = Chat.Read();
if(ret!=null && ret.error!=null)
{
alert("A critical error ocurred: " + new String(ret.error).replace(
"System.Exception ","") +
"\nPlease reload page to try again.");
return;
}
var value = ret.value;
if(value!=null && value!="")
{
var otxtChatFrame =
document.getElementById("<%=txtChatFrame.ClientID%>");
var already_read = otxtChatFrame.value;
//var all = value + already_read;
var all = already_read + value;
if(all!="")
{
var arr = all.split("\n");
if(arr.length>max_chat_lines)
{
all = "";
//for(var i=0; i<max_chat_lines; i++)
for(var i=(arr.length-max_chat_lines); i<arr.length; i++)
all += arr[i] + "\n";
}
}
otxtChatFrame.value = all;
// Scroll down to the last read line
otxtChatFrame.scrollTop=otxtChatFrame.scrollHeight;
}
window.setTimeout("Reload();", reload_wait);
}
function Start()
{
Reload();
// Initial scroll down to the last read line (in case Refresh is hit)
var otxtChatFrame = document.getElementById("<%=txtChatFrame.ClientID%>");
otxtChatFrame.scrollTop=otxtChatFrame.scrollHeight;
}
function LoggedIn()
{
var otxtName = document.getElementById("txtName");
var obtnSend = document.getElementById("btnSend");
var otxtMssg = document.getElementById("txtMssg");
last_user_name = otxtName.value;
otxtName.disabled = false;
obtnSend.disabled = false;
otxtMssg.disabled = false;
otxtMssg.focus();
}
// Call to start!
Start();
</script>
</form>
</body>
</html>
Page code-behind
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Threading;
using System.Globalization;
public partial class ChatPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Ajax.Utility.RegisterTypeForAjax(typeof(SpilafisChatLogic.Chat));
UpdateUsersGridView();
}
public void UpdateUsersGridView()
{
grvUsers.DataSource = SpilafisChatLogic.Chat.GetUsersDataSource();
grvUsers.DataBind();
}
protected void btnRefresh_ServerClick(object sender, EventArgs e)
{
UpdateUsersGridView();
}
}
Business logic
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Threading;
using System.Globalization;
namespace SpilafisChatLogic
{
public class Business
{
public Business()
{
}
public static User CurrentUser
{
get
{
if (HttpContext.Current.Session["ChatCurrentUser"] == null)
HttpContext.Current.Session["ChatCurrentUser"] = new User();
return (User)HttpContext.Current.Session["ChatCurrentUser"];
}
set
{
HttpContext.Current.Session["ChatCurrentUser"] = value;
}
}
public static App CurrentApp
{
get
{
if (HttpContext.Current.Application["ChatCurrentApp"] == null)
HttpContext.Current.Application["ChatCurrentApp"] = new App();
return (App)HttpContext.Current.Application["ChatCurrentApp"];
}
set
{
HttpContext.Current.Application["ChatCurrentApp"] = value;
}
}
}
public class User
{
#region Private Members
private bool m_ajax_chat_counted;
private string m_ajax_chat_user_name;
private int m_ajax_chat_last_read_id;
private bool m_code_access_enabled;
#endregion
public User()
{
m_ajax_chat_counted = false;
m_ajax_chat_user_name = "";
m_ajax_chat_last_read_id = -1;
m_code_access_enabled = false;
}
#region Properties
public bool AjaxChatCounted
{
get { return m_ajax_chat_counted; }
set { m_ajax_chat_counted = value; }
}
public string AjaxChatUserName
{
get { return m_ajax_chat_user_name; }
set { m_ajax_chat_user_name = value; }
}
public int AjaxChatLastReadId
{
get { return m_ajax_chat_last_read_id; }
set { m_ajax_chat_last_read_id = value; }
}
#endregion
}
public class App
{
#region Private Members
private int m_ajax_chat_users_r;
private Hashtable m_ajax_chat_users_w;
private Hashtable m_ajax_chat_users_w_last_activity;
private ArrayList m_ajax_chat;
#endregion
public App()
{
m_ajax_chat_users_w = new Hashtable();
m_ajax_chat_users_w_last_activity = new Hashtable();
m_ajax_chat = new ArrayList();
}
#region Properties
public int AjaxChatUsersR
{
get { return m_ajax_chat_users_r; }
set { m_ajax_chat_users_r = value; }
}
public Hashtable AjaxChatUsersW
{
get { return m_ajax_chat_users_w; }
set { m_ajax_chat_users_w = value; }
}
public Hashtable AjaxChatUsersWLastActivity
{
get { return m_ajax_chat_users_w_last_activity; }
set { m_ajax_chat_users_w_last_activity = value; }
}
public ArrayList AjaxChat
{
get { return m_ajax_chat; }
set { m_ajax_chat = value; }
}
#endregion
}
public class Chat
{
#region Constants
public static int MaxMessageLength = 100;
public static int MaxChatLines = 50;
public static int MaxLoggedInUsers = 5;
public static string[] BadWords = { "a**hole",
"boludo"};
#endregion
public Chat()
{
}
#region Methods
private static void IncrementUsersReading()
{
Business.CurrentApp.AjaxChatUsersR = GetIntUsersReading() + 1;
}
private static int GetIntUsersReading()
{
return Business.CurrentApp.AjaxChatUsersR;
}
private static int GetId(string message)
{
return Convert.ToInt32(message.Split('-')[0]);
}
private static string GetMessage(string message)
{
return message.Split('-')[1];
}
private static string GetNextId(ArrayList ajax_chat_list)
{
int id = GetMaxId(ajax_chat_list);
if (id < Int32.MaxValue)
id++;
else
id = 0;
return id.ToString() + "-";
}
private static int GetMaxId(ArrayList ajax_chat_list)
{
if (ajax_chat_list.Count > 0)
return GetId(ajax_chat_list[0].ToString());
else
return 0;
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static string GetUserName()
{
if (Business.CurrentUser.AjaxChatUserName == "")
Chat.GetNextUserName();
return Business.CurrentUser.AjaxChatUserName;
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static string GetNextUserName()
{
string user_name = "";
if (!Business.CurrentUser.AjaxChatCounted)
{
Business.CurrentUser.AjaxChatCounted = true;
IncrementUsersReading();
}
else
{
if (Business.CurrentUser.AjaxChatUserName != null &&
Business.CurrentUser.AjaxChatUserName != "")
return Business.CurrentUser.AjaxChatUserName;
}
int user_number = Business.CurrentApp.AjaxChatUsersW.Count + 1;
if (user_number <= MaxLoggedInUsers)
{
while (Business.CurrentApp.AjaxChatUsersW["ChatGuest" +
user_number.ToString()] != null)
{
if (user_number < int.MaxValue)
user_number++;
else
return "";
}
Business.CurrentApp.AjaxChatUsersW.Add("Guest" +
user_number.ToString(), 1);
Business.CurrentUser.AjaxChatUserName =
"Guest" + user_number.ToString();
UpdateUserLastActivityTime();
}
return user_name;
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static void ChangeUserName(string tentative_name)
{
if (Business.CurrentUser.AjaxChatUserName == "")
{
int user_number = Business.CurrentApp.AjaxChatUsersW.Count + 1;
if (user_number > MaxLoggedInUsers)
throw new Exception("Max. number of writing " +
"users reached. You'll be inform when someone leaves.");
}
tentative_name = tentative_name.Trim();
if (tentative_name == "")
throw new Exception("You must enter a user name to be able to chat.");
if (tentative_name.IndexOf('-') >= 0)
throw new Exception("Character '-' is not allowed in the user name.");
if (tentative_name.Length > 10)
tentative_name = tentative_name.Substring(0, 10);
if (Business.CurrentApp.AjaxChatUsersW[tentative_name] != null)
throw new Exception("User name already in use. Please enter another.");
ChangeUserNameInWList(tentative_name);
Business.CurrentUser.AjaxChatUserName = tentative_name;
UpdateUserLastActivityTime();
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static void ChangeUserNameInWList(string new_name)
{
if (Business.CurrentUser.AjaxChatUserName != null &&
Business.CurrentUser.AjaxChatUserName != "")
{
Business.CurrentApp.AjaxChatUsersW.Remove(
Business.CurrentUser.AjaxChatUserName);
Business.CurrentApp.AjaxChatUsersWLastActivity.Remove(
Business.CurrentUser.AjaxChatUserName);
Business.CurrentApp.AjaxChatUsersW.Add(new_name, 1);
}
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static void Post(string message)
{
message = message.Trim();
if (message.Length > MaxMessageLength)
message = message.Substring(0, MaxMessageLength);
if (message != "")
{
string message_head =
Business.CurrentUser.AjaxChatUserName + " says: ";
message = message_head + message;
ValidateMessage(Business.CurrentApp.AjaxChat, message);
message = GetNextId(Business.CurrentApp.AjaxChat) + message;
Business.CurrentApp.AjaxChat.Insert(0, message);
while (Business.CurrentApp.AjaxChat.Count > MaxChatLines)
Business.CurrentApp.AjaxChat.RemoveAt(
Business.CurrentApp.AjaxChat.Count - 1);
UpdateUserLastActivityTime();
}
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static void ValidateMessage(ArrayList ajax_chat_list, string message)
{
int index;
ArrayList ajax_chat_nonumbers = new ArrayList();
for (index = 0; index < ajax_chat_list.Count; index++)
ajax_chat_nonumbers.Add(ajax_chat_list[index].ToString().Split('-')[1]);
if (ajax_chat_nonumbers.Contains(message))
throw new Exception("Please no spam...");
string[] m_w = message.Replace("\n", " ").Replace("\r", "").Split(' ');
ArrayList message_words = new ArrayList();
for (index = 0; index < m_w.Length; index++)
message_words.Add(m_w[index]);
for (index = 0; index < BadWords.Length; index++)
if (message_words.Contains(BadWords[index]))
throw new Exception("Please no bad words...");
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static void UpdateUserLastActivityTime()
{
if (Business.CurrentUser.AjaxChatUserName != null &&
Business.CurrentUser.AjaxChatUserName != "")
UpdateUserLastActivityTime(
Business.CurrentApp.AjaxChatUsersWLastActivity);
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static void UpdateUserLastActivityTime(
Hashtable ajax_chat_users_w_last_activity)
{
if (ajax_chat_users_w_last_activity<Business.CurrentUser.AjaxChatUserName>
== null)
ajax_chat_users_w_last_activity.Add(
Business.CurrentUser.AjaxChatUserName, DateTime.Now);
else
ajax_chat_users_w_last_activity<
Business.CurrentUser.AjaxChatUserName> = DateTime.Now;
}
public static DataTable GetUsersDataSource()
{
DataTable dtSource = new DataTable();
dtSource.Columns.Add(new DataColumn("ChatUsers"));
dtSource.Columns.Add(new DataColumn("ChatLastActivity"));
DataRow drSource;
DateTime last_activity;
if (Business.CurrentApp.AjaxChatUsersW.Keys.Count > 0)
{
foreach (object key in Business.CurrentApp.AjaxChatUsersW.Keys)
{
drSource = dtSource.NewRow();
drSource["ChatUsers"] = key.ToString();
if (Business.CurrentApp.AjaxChatUsersWLastActivity[key] != null)
{
last_activity =
(DateTime)Business.CurrentApp.AjaxChatUsersWLastActivity[key];
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
string dateFormat =
CultureInfo.InvariantCulture.DateTimeFormat.RFC1123Pattern.Replace(
"'GMT'", "zzz");
string dateString = last_activity.ToString(dateFormat);
drSource["ChatLastActivity"] = dateString;
}
else
drSource["ChatLastActivity"] = "<none>";
dtSource.Rows.Add(drSource);
}
}
else
{
drSource = dtSource.NewRow();
drSource["ChatUsers"] = "<none>";
drSource["ChatLastActivity"] = "<none>";
dtSource.Rows.Add(drSource);
}
dtSource.DefaultView.Sort = "ChatUsers";
return dtSource;
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static string Read()
{
int id;
int max_id = 0;
string message;
System.Text.StringBuilder chat = new System.Text.StringBuilder();
ArrayList ajax_chat_list = Business.CurrentApp.AjaxChat;
int last_read_id = Business.CurrentUser.AjaxChatLastReadId;
int index;
ArrayList chat_arr = new ArrayList();
for (index = 0; index < ajax_chat_list.Count; index++)
{
id = GetId(ajax_chat_list[index].ToString());
if (index == 0)
max_id = id;
message = GetMessage(ajax_chat_list[index].ToString());
if (id == last_read_id)
break;
chat_arr.Add(System.Web.HttpUtility.HtmlEncode(message) + "\n");
}
for (index = chat_arr.Count - 1; index >= 0; index--)
chat.Append(chat_arr[index].ToString());
Business.CurrentUser.AjaxChatLastReadId = max_id;
UpdateUserLastActivityTime();
return chat.ToString();
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static string GetUsersWriting()
{
return Business.CurrentApp.AjaxChatUsersW.Count.ToString();
}
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
public static string GetUsersReading()
{
return GetIntUsersReading().ToString();
}
#endregion
}
}
See a working example here: http://spilafis.com.ar/ChatPage.aspx.
Or a more complex (same code but enhanced) but better working example: http://spilafis.com.ar/ChatAjaxNet.aspx.
License and Disclaimer
All the instructions, code, HTML, and everything else presented in this page is provided 'as is' with no warranties what so ever. The only condition for you to use this software is that you keep the link to http://www.spilafis.com.ar in the chat page as provided. Please support freeware, keeping the link.