Basic Chat Using ASP .NET AJAX

Published 01 March 07 09:49 PM | Coding4Fun 

 

The AJAX Chat Sample shows how to build a browser based chat using ASP .NET and AJAX. ASP.NET AJAX is the easiest and most enjoyable way to start writing asynchronous Web applications using ASP.NET. The official ASP.NET AJAX site is here, and you will want to make sure you have downloaded the last version of the framework and the control toolkit before continuing with this example.

 


Difficulty: Easy
Time Required: 1-3 hours
Cost: Free
Software: Visual Basic or Visual C# Express Editions
Hardware:
Download: Download

    The Code

    Here’s an overview of the basic chat logic; it’s very simple—

    1. A user accesses a page, and a new Chatter object is initialized
    2. The page class determines which Chats are available in the current application context on the server
    3. The page class calls the Chatter’s Join method to associate the Chatter with the appropriate Chat object
    4. The Chatter begins calling the Chat’s SendMessage method to post new messages
    Create an ASP.NET AJAX-Enabled Web Site and Enable Partial Rendering

    To begin, create a new ASP.NET AJAX-Enabled Web Site in Visual Studio 2005

     

    The Default.aspx file created in the new project should contain the following:

     

    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" />
    </form>
     

    Before continuing, add the EnablePartialRendering="true" attribute to the ScriptManager control. This enables you to update regions of the page individually by using UpdatePanel controls (more on that later!). You will also want to copy the App_Code folder from this examples downloadable files to your project directory. The two class files “Chat.cs” and “Chatter.cs” are needed to create our test data.

    Add Some Chat Controls

    We’ll need three controls right away: a BulletedList to show all of the Chatters participating in the Chat, another BulletedList (part of the control toolkit) to display chat messages (from the server application), and a TextBox to enter new chat messages (from your client browser). You may wonder why we are using a BulletedList to display chat messages rather than a TextBox or ListBox control. It would certainly be possible to use either of those alternatives, however a BulletedList allows for more flexibility when styling the HTML output, and by setting the control’s CSS overflow style to auto we can create a ListBox-like experience pretty easily.

    <asp:BulletedList ID="ChattersBulletedList" runat="server" />
    <asp:BulletedList runat="server" ID="ChatMessageList" />
    <asp:TextBox ID="NewMessageTextBox" Columns="50" runat="server" />
    
    We’ll also add a button that we will later use to trigger an asynchronous call back to 
     
    Default.aspx:
    <asp:Button ID="SendButton" Text="Send" runat="server" OnClick="SendMessage_Click"/>
    The complete form should look something like this:
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" />
    Chatters<br/>
    <asp:BulletedList ID="ChattersBulletedList" runat="server" />
    Chat Text<br/>
    <div style="width: 640px; height: 240px; overflow: auto;">
    <asp:BulletedList runat="server" ID="ChatMessageList" />
    </div>
    Send Message Text<br/>
    <asp:TextBox ID="NewMessageTextBox" Columns="50" runat="server" /><asp:Button ID="SendButton" Text="Send" runat="server" />
    </form>
     

    At this point you can run the project and check out the form.

    Add Some Chatters

    In a real-world scenario you would of course implement some kind of user authentication for your application. For the purposes of this example we will skip all of that and simply hard-code our chat application participants in the Application context. To do this, add a new Global.asax file to your project by right-clicking the project in the solution tree, clicking “Add New Item” and choosing Global Application Class.

    Since we want to simulate a group of Chatters that have logged into our site, we will create a list of Chatter objects within the Application_Start method like so—

    C#
    List<Chatter> chatters = new List<Chatter>();
    chatters.Add(new Chatter(new Guid("CD863C27-2CEE-45fd-A2E0-A69E62B816B9"), "Me"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Juan"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Joe"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Eric"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Brian"));
    chatters.Add(new     Chatter(Guid.NewGuid(), "Kim"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Victor"));
    Application.Add("Chatters", chatters);
    VB
    Dim chatters As List(Of Chatter) = New List(Of Chatter)
    chatters.Add(New Chatter(New Guid("CD863C27-2CEE-45fd-A2E0-A69E62B816B9"), "Me"))
    chatters.Add(New Chatter(Guid.NewGuid, "Juan"))
    chatters.Add(New Chatter(Guid.NewGuid, "Joe"))
    chatters.Add(New Chatter(Guid.NewGuid, "Eric"))
    chatters.Add(New Chatter(Guid.NewGuid, "Brian"))
    chatters.Add(New Chatter(Guid.NewGuid, "Kim"))
    chatters.Add(New Chatter(Guid.NewGuid, "Victor"))
    Application.Add("Chatters", chatters)
     

    (Be sure to add <%@ Import Namespace="System.Collections.Generic" %> at the top of the file.) This is clearly test-only data, but the import thing to note is that each Chatter gets a new random Guid except for “Me” which gets a hard-coded value. In a real-world scenario this would probably be a user identification number stored in a cookie or Session variable, but since we are lazy, we will simply have hard-code it in two places to get a similar effect.

    Next we will create a list of Chat’s available in the application (just one for now)—

    List<Chat> chat = new List<Chat>();
    chat.Add(new Chat());
    Application.Add("Chats", chat);
     

    Finally, we will loop through our list of logged-in users and associate them with the single Chat instance added above—

    C#
    foreach (KeyValuePair<Guid, Chatter> chatter in Chatter.ActiveChatters())
    {
    chatter.Value.Join(Chat.ActiveChats()[0]);
    }
    
    VB
    For Each c As KeyValuePair(Of Guid, Chatter) In Chatter.ActiveChatters
    c.Value.Join(Chat.ActiveChats(0))
    Next
     

    The Global.asax code should look something like this—

     

    C#
    void Application_Start(object sender, EventArgs e) 
    {
    List<Chatter> chatters = new List<Chatter>();
    chatters.Add(new Chatter(new Guid("CD863C27-2CEE-45fd-A2E0-A69E62B816B9"), "Me"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Juan"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Joe"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Eric"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Brian"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Kim"));
    chatters.Add(new Chatter(Guid.NewGuid(), "Victor"));
    Application.Add("Chatters", chatters);
    
    List<Chat> chats = new List<Chat>();
    chats.Add(new Chat());
    Application.Add("Chats", chats);
    
    foreach (KeyValuePair<Guid, Chatter> chatter in Chatter.ActiveChatters())
            {
                chatter.Value.Join(Chat.ActiveChats()[0]);
            }
    }
    VB
    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    Dim chatters As List(Of Chatter) = New List(Of Chatter)
    chatters.Add(New Chatter(New Guid("CD863C27-2CEE-45fd-A2E0-A69E62B816B9"), "Me"))
    chatters.Add(New Chatter(Guid.NewGuid, "Juan"))
    chatters.Add(New Chatter(Guid.NewGuid, "Joe"))
    chatters.Add(New Chatter(Guid.NewGuid, "Eric"))
    chatters.Add(New Chatter(Guid.NewGuid, "Brian"))
    chatters.Add(New Chatter(Guid.NewGuid, "Kim"))
    chatters.Add(New Chatter(Guid.NewGuid, "Victor"))
    Application.Add("Chatters", chatters)
    Dim chats As List(Of Chat) = New List(Of Chat)
    chats.Add(New Chat)
    Application.Add("Chats", chats)
    For Each c As KeyValuePair(Of Guid, Chatter) In Chatter.ActiveChatters
    c.Value.Join(Chat.ActiveChats(0))
    Next
    End Sub
     

    When the test server first runs our project the code path above will be invoked and we will have a magical list of users in the Application context ready to chat away.

    Handle Some Events

    Open the code-behind file for Default.aspx (Default.aspx.cs) and add two private variables: one for our Chatter (“Me”), and one for the single Chat instance—

    // You’ll notice these are the same values hard-coded in the Global.asax file as well
    private Chat m_chat = Chat.ActiveChats()[0];
    private Chatter m_chatter = Chatter.ActiveChatters()[new Guid("CD863C27-2CEE-45fd-A2E0-A69E62B816B9")];
    
    Next, add a private method called _UpdateChatterList—
    
    private void _UpdateChatterList()
    {
    ChattersBulletedList.DataSource = m_chat.Chatters;
    ChattersBulletedList.DataTextField = "Name";
    ChattersBulletedList.DataBind();
    }
    
     

    Since Chatters will enter and leave the Chat at any time, our global list of Chatters will need to update often. _UpdateChatterList binds our global list of Chatters to the appropriate BulletedList in the Web form every time we post-back to this page. We’ll also need to update and display the list of messages from our Chat instance. To do this we’ll add a new method called _UpdateChatMessageList—

    C#
    private void _UpdateChatMessageList()
    {
    ChatMessageList.DataSource = m_chat.Messages;
    ChatMessageList.DataBind();
    }
    VB
    Private Sub _UpdateChatMessageList()
    ChatMessageList.DataSource = m_chat.Messages
    ChatMessageList.DataBind()
    End Sub
     

    Any messages that have been pushed to our Chat instance since the last post-back will now be appended to our Chat message BulletedList.

    The last thing we need to do is handle the button click that occurs when a Chatter sends a new message to the Chat instance. To do this add an OnClick attribute to the “Send” button in Default.aspx—

    <asp:Button ID="SendButton" Text="Send" runat="server" OnClick="SendButton_Click" />
     

    Then, add the event handler for the button click to the code-behind. We’ll also call our “Update” methods after sending our chat message—

    C#
    protected void SendButton_Click(object sender, EventArgs e)
    {
    if (!string.IsNullOrEmpty(NewMessageTextBox.Text))
    {
    string messageSent = m_chat.SendMessage(m_chatter, NewMessageTextBox.Text);
    }
    _UpdateChatterList();
    _UpdateChatMessageList();
    }
    VB
    Protected Sub SendButton_Click(ByVal sender As Object, ByVal e As EventArgs)
    If Not String.IsNullOrEmpty(NewMessageTextBox.Text) Then
    Dim messageSent As String = m_chat.SendMessage(m_chatter, NewMessageTextBox.Text)
    NewMessageTextBox.Text = String.Empty
    End If
    _UpdateChatterList()
    _UpdateChatMessageList()
    End Sub
     

    This will handle the click event from the “Send” button, check if we have any text to send, then call our Chat’s SendMessage method which will add the message to our global Chat object.

    Try It Out!

    Try running the project and sending a few messages. The page will do a complete post-back to the server every time the “Send” button is clicked. Lame. Let’s get rid of that by using the ASP.NET AJAX UpdatePanel.  Download the sample project.

    UpdatePanel: The Key to ASP.NET Async Happiness

    Recall that in the first step we added the EnablePartialRendering attribute to the ScriptManager control. Now we can actually use that functionality by wrapping our Chat controls in an UpdatePanel. In the Default.aspx file encapsulate the BulletedList controls with an UpdatePanel as follows—

    <asp:UpdatePanel ID="ChatUpdatePanel" runat="server" UpdateMode="Always">
    <ContentTemplate>
    Chatters<br/>
    <asp:BulletedList ID="ChattersBulletedList" runat="server" />
    Chat Text<br/>
    <div style="width: 640px; height: 240px; overflow: auto;">
    <asp:BulletedList runat="server" ID="ChatMessageList" />
    </div>
    </ContentTemplate>
    </asp:UpdatePanel>
     

    (Note that you must add a ContentTemplate element to the UpdatePanel before adding the Web controls.)

    To circumvent the normal post-back processing we need to associate this UpdatePanel with a “Trigger,” so after the close of the ContentTemplate element add the following—

    <Triggers>
    
    <asp:AsyncPostBackTrigger ControlID="SendButton" EventName="Click" />
    
    </Triggers>
    
    

    Now “Send” button clicks will be handled asynchronously, and we don’t have to modify any of the synchronous logic we implemented above. Pretty nice!

    One Last Trigger

    Our chat application doesn’t quite work as we’d expect it to yet. We really want the list of messages to update continuously as new messages are sent from other Chatters. We can implement this by adding a new Trigger to the Triggers element, and wiring the new Trigger to a Timer control—

    ...

    <asp:AsyncPostBackTrigger ControlID="ChatTextTimer" EventName="Tick" />
    
    </Triggers>
    
    

    Then, add a Timer control to the page. The Interval attribute determines the amount of time between “ticks” of the timer (in milliseconds)—

    <asp:Timer runat="server" ID="ChatTextTimer" Interval="1000" />

    Finally, add calls to UpdateChatterList and UpdateChatMessageList in the Page_Load event handler. When the timer Tick event fires the page will post-back, the Page_Load handler will be invoked and our message list and Chatter list will update as expected. With these changes in place go ahead and run the project again. You may notice that the message list resets its scroll position to the top every time it updates. To fix this add the following JavaScript block after the closing form tag and before the closing body tag in Default.aspx—

    <script type="text/javascript">
    
    function _SetChatTextScrollPosition()
    
    {
    
    var chatText = document.getElementById("ChatText");
    
    chatText.scrollTop = chatText.scrollHeight;
    
    window.setTimeout("_SetChatTextScrollPosition()", 1);
    
    }
    
    window.onload = function()
    
    {
    
    _SetChatTextScrollPosition();
    
    }
    
    </script>
    
    

    The list will flicker slightly as it repositions itself, but the latest message will stay in view at the bottom of the list.

    To test the functionality of your new chat application connect to the test URL with two separate browser windows and type messages into one or the other. You should see your messages pop into the message list of each one no matter which browser sends the message. Enjoy!

    Download

    Download the sample project.

    Bio

    “Tyler Schlegel is a Software Development Engineer with Personify Design, Inc. He’s been developing .NET solutions since 2002.”

    Filed under:

    Comment Notification

    If you would like to receive an email when updates are made to this post, please register here

    Subscribe to this post's comments using RSS

    Comments

    # hannespreishuber said on March 2, 2007 2:04 AM:

    The download link shows up a 404

    # dada said on March 22, 2007 7:19 PM:

    Is it just me, or is it now not working on final build of ASP.NET 2.0 Ajax Extensions 1.0?!

    Microsoft.Web.Extensions.dll missing?!@

    # Dada said on April 7, 2007 3:34 AM:

    Is it just me or chat stops working once you add an autocompleteextender code from ajaxcontroltoolkit samples in the same page?!? My guess is it's some timer problem but I can't figure out how to fix it? Any ideas?!

    # adam.edmonds said on April 9, 2007 12:06 PM:

    Any news on the download link?

    Thanks,

    Adam

    # scottt40 said on April 19, 2007 9:10 AM:

    What would be the mods you would have to  make to enable asp.net 2.0 membership instead of static chatters?

    # clernest said on April 24, 2007 10:27 PM:

    Hey DaDa go to the Web.config and replace every instance of Microsoft to System.  That will handle the missing dll problem.  MS renamed the class.

    # Sanjay said on April 30, 2007 2:45 PM:

    Its really very help ful I could implemnt chat by using this method. Thanks a lot

    Sunit

    www.SuperShaadi.com

    # Gabe said on May 10, 2007 9:27 PM:

    Here is a good download link.

    http://channel9.msdn.com/ShowPost.aspx?PostID=287377

    # Abbas said on May 23, 2007 8:18 PM:

    Very nice example, it gave me a better view on the possibilities and power of AJAX.NET!!

    # Vasundhara said on May 30, 2007 3:22 AM:

    Hi,

    Very useful example.

    But i have a samll doubt.

    I have downloaded this project

    when i open this project in Visual studio.net 2005

    I am getting error at the chat.vb and chatter.vb saying the 'Type Chatter is not defined'

    Please can you help me in solving this problem

    my id is mylavarapu.vasundhara@gmail.com

    # Mason Cox said on June 20, 2007 6:52 AM:

    I've been trying for ages to try and write a shoutbox in .NET, finally I have the answer! Thanks for this!

    # Mike said on June 28, 2007 10:47 AM:

    download link still inactive, and code seems to be cut off in IE and Firefox. Little tough to follow with those problems.

    # sorcerer said on July 12, 2007 6:57 AM:

    the download link ???.. redirects to the same page without prompting for the download dialog box

    # mike said on August 12, 2007 8:09 PM:

    link is not working!! please help!!

    # Hassan Ali said on August 14, 2007 4:21 AM:

    can i use this chat application for one to many chat where at one of the other end (many) i want to maintain a queue, so basically one to one chat and one is done with chatting, the other in the queue will get active.

    # Visualbb said on October 20, 2007 11:01 PM:

    This download link links back to this page - endless circle. Are you going to fix it?

    # derrick said on October 29, 2007 6:34 PM:

    The link to download is invalid... please provide info on how to download the cs modules.

    # Coding4Fun said on October 29, 2007 8:19 PM:

    Hey guys, sorry about the link.  The link at the bottom worked and I fixed the link on the top.

    # its wonderfull said on November 25, 2007 6:50 AM:

    but how can we make the login for this chat

    # Pragman said on December 10, 2007 4:17 PM:

    Try and use a query string to pass a users "login" information to the chat. Theres probably a number of ways to enable logging in instead of using the static method above.

    # paul said on January 14, 2008 4:14 PM:

    has anyone figured out how to use the login method?

    # JND said on January 26, 2008 5:47 PM:

    Does Anyone have an example on the use of non static chatters? I am a bit hung up on the concept. Just need a decent example to get me going.

    Awsome work and thank you for your time.

    JND

    # Coding4Fun said on February 1, 2008 2:03 PM:

    @JND: non static chatters?

    # benjamin said on February 9, 2008 5:58 AM:

    how can i fix  or choose a chatter updating chatters?

    # Wales said on February 15, 2008 3:01 PM:

    how to update the Active Chatter List based on Login and Logout users?

    # Vikash said on March 18, 2008 7:02 AM:

    How to avoid flickering while reload?

    # ramu said on May 30, 2008 6:02 AM:

    i luv chating though idont know it perfectly

    # Iran said on June 28, 2008 8:40 PM:

    How can this be implemented to one to one chat.

    Thanks.

    This is a great share man.

    # Ariful Ambia Noman said on June 30, 2008 3:46 AM:

    this is what i am looking for.

    # Mr.A said on July 2, 2008 4:46 PM:

    still no login method available? Its the only thing that require to make it looks awesome.

    # Coding4Fun said on July 2, 2008 10:19 PM:

    @Mr.A: We provide a working model, if you want to extend it to include login, it shouldn't be too hard.

    # Riccardo said on July 15, 2008 6:52 AM:

    How can i Use this Basic chat as an Instant Messenger among only two user?

    Thanks

    Riccardo

    # Coding4Fun said on July 16, 2008 2:33 PM:

    @Riccardo:  I can't see why not

    # Kyle said on August 8, 2008 9:42 AM:

    What is the proper way to remove a current chatter from the Application?

    # Randy said on October 30, 2008 9:03 PM:

    How would you recommend handling that a user can't scroll up? This is due to the message list is updating every second. The javascript jumps to the bottom every second.

    # Coding4Fun said on November 5, 2008 1:01 PM:

    @Randy I would add in some javascript to check if a user scrolled up.  If they did then don't jump down

    # Alton said on December 5, 2008 2:13 AM:

    DNS not resolved, cannot download code.

    # jeksya said on December 5, 2008 7:50 PM:

    download  link does not work again =((((

    # Coding4Fun said on December 8, 2008 3:19 PM:

    @Alton @jeksya working on getting the source and will move it to our server instead

    # Coding4Fun said on December 8, 2008 7:39 PM:

    @Alton @jeksya Personify Design gave me the source code and links have been updated.  Should work now.

    # pwn said on January 22, 2009 2:17 AM:

    hi, very nice example to get up and going, but it would be nice if you also updated the web.config

    I copied the web.config from a default asp.net 3.5 project and the whole thing compiled fine after that.

    # Dave Violette said on February 13, 2009 9:40 AM:

    "@Randy I would add in some javascript to check if a user scrolled up.  If they did then don't jump down"

    Can someone help me with the code for this? I am not javascript expert.

    Also, any help in getting rid of flickering?

    # rahul said on March 2, 2009 12:12 AM:

    i am not able to download this link

    # Coding4Fun said on March 13, 2009 5:56 PM:

    @rahul Link at the top of the page labeld "Download" worked for me.

    # mickey said on April 7, 2009 2:33 PM:

    Can your chatters be added live or do they need to be preloaded as above in the global asax

    # lost said on May 30, 2009 11:06 AM:

    I am a total noob on what to do after downloading the zip file. I hope someone can guide me how to test it. I tried opening the project in visual basic 2008 but there is no project file from the sample. I really have no idea what to do next. :)

    # Coding4Fun said on May 31, 2009 5:50 PM:

    @lost, Looks like you'll have to create a new project to run this.  sadly, looks like this example doesn't have a project file.

    I would follow the article and copy the code out of the files to recreate it.

    # Marvin d Martian said on June 4, 2009 12:23 AM:

    has anyone tried extending the code to add login functions? Ive tried but the messages from other chatters won't show up.

    # Monoko said on June 6, 2009 9:53 AM:

    Hey I'm using this basic code for a chat that I'm about to create but I cant figure out how and where to add a function that adds the users dynamically? Can anyone help me?

    # FishGuy said on June 26, 2009 7:38 AM:

    I am getting error at the chat.vb and chatter.vb saying the 'Type Chatter is not defined'

    Please can you help me in solving this problem?

    I have the same issue!

    Leave a Comment

    (required) 
    (optional)
    (required) 
    Page view tracker