Click here to Skip to main content
15,867,568 members
Articles / Web Development / ASP.NET

ASP.NET Chatting using WCF Services and JSon

Rate me:
Please Sign up or sign in to vote.
4.75/5 (30 votes)
1 Dec 2011CPOL5 min read 160.3K   17.4K   110   62
ASP.NET chatting using WCF Services and JSon

Introduction

This post is an upgrade to my previous article 'Chat Application in ASP.NET Using AJAX (Pop-up Windows)', which has some disadvantages like storing chat messages in DB and little complex in adding to a website. I implemented WCF services in place of DB to make it easy for adding to a website. JSon is used for communication between server and client.

Using the Code

The basic idea is the same as the previous one, but it was modified to improve support to multiple browsers. When I ran the application on three major browsers, IE, Firefox, Chrome, it was working perfect.

If you already read the previous article, you can skip the work flow and go to the configuration section.

The application works as follows:

  • List of online users are displayed.

    Online users list is maintained by WCF service OnlineUsers.svc, logging an entry when a user logs into the application. The user names will be displayed as hyperlinks, with a unique chat ID (GUID) for each.

  • The current logged-in user will click on a user name to open a new chat window, and types a message. 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.
    JavaScript
    var top = 100;
    var left = 100;
    function OpenChatBox(uid, chatid) 
    {    
        var hidUsr = $('input[id*="hidCurrentUser"]')[0];
        if (hidUsr.value == uid)
            return;
        var win;
        if (navigator.userAgent.toLowerCase().indexOf("chrome") != -1)
            win = window.open("Chat.aspx?uid=" + uid + "&cid=" + 
            chatid, "ChatWindow" + chatid.replace("-", "").replace
            ("-", "").replace("-", "").replace("-", ""), 
            "status=0,toolbar=0, menubar=0, width=480, height=620");
        else
            win = window.open("Chat.aspx?uid=" + uid + "&cid=" + 
            chatid, "ChatWindow" + chatid.replace("-", "").
            replace("-", "").replace("-", "").
            replace("-", ""), "status=0,toolbar=0, menubar=0, width=480, 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 as below. Here I am using class 'ChatMsg' (DataContract) to pass messages to chat service.

    JavaScript
    private void SendMessage(string msg)
    {
        ChatServiceClient objChatService = new ChatServiceClient();
        ChatMsg cm = new ChatMsg();        
        cm.Msg = msg;
        cm.Sender = HttpContext.Current.User.Identity.Name;
        cm.Receiver = ViewState["uid"].ToString();
        cm.ChatId = ViewState["vwChatId"].ToString();
        cm.SubmittedDate = DateTime.Now;
        objChatService.SendMessage(cm);        
    }

    Chat_Flow.jpg

  • On the recipient's screen, a new pop-up window will appear.

    One every user's home page, a script is run every 5 seconds to ping the server for any messages.

    JavaScript
    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 GetChat.aspx page for new messages. Here I am calling the WCF service '' to get messages and the messages will be sent to client in JSon. I am using 'JsonConvert' class from JSon.Net to serialize the list of messages. You no need to learn JSon for this application as the download includes the JSon ddl and no extra downloads are required.

    Code from GetChat.aspx.cs:

    C#
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Data;
    using WCFChatProxy;
    using Newtonsoft.Json;
    
    public partial class GetChat : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Request.QueryString["p"] != null)
            {
                if (Request.QueryString["p"] == "read")
                {
                    ChatServiceClient objChat = new ChatServiceClient();
                    objChat.MessageStatusToRead(Request.QueryString["msgId"]);
                }
            }
            else if (Request.QueryString["cid"] != null)     //get messages for a 
                            //single chat window
            {
                Response.Clear();
                Response.ClearContent();
                Response.AddHeader("Cache-Control", "no-cache, must-revalidate");
    
                ChatServiceClient objChatService = new ChatServiceClient();
                List<chatmsg> lstMsgs = objChatService.GetMessages
                    (Request.QueryString["cid"].ToString(),
                    HttpContext.Current.User.Identity.Name,
            ChatMsgStatus.Recent).ToList();
    
                string strMsg = JsonConvert.SerializeObject(lstMsgs);
    
                Response.Write(strMsg);
                Response.End();
            }
            else // get messages for the current logged in user
            {
                Response.Clear();
                Response.ClearContent();
                Response.AddHeader("Cache-Control", "no-cache, must-revalidate");
    
                ChatServiceClient objChatService = new ChatServiceClient();
                List<chatmsg> lstMsgs = objChatService.GetMessagesByUserId
                (HttpContext.Current.User.Identity.Name).ToList();
    
                string strMsg = JsonConvert.SerializeObject(lstMsgs);
    
                Response.Write(strMsg);
                Response.End();
            }
        }
    }

    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. And here, an additional change to the old article is that on receiving message, browser sends an acknowledgement to server and server marks the message as read.

    JavaScript
    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 != "") {  
                var chatmsgs = eval(str);
                for (ind = 0; ind < chatmsgs.length; ind++) {
                    var senderId = chatmsgs[ind].Sender;
                    var chatId = chatmsgs[ind].ChatId;
                    var message = chatmsgs[ind].Msg;
                    var msgId = chatmsgs[ind].MsgId;
    
                    message = restoreHtmlTags(message);
                    document.getElementById('msgPanel').innerHTML += "
    " + senderId + ": " + message;
                    MessageReceived(msgId, msgCounter);
    
                    document.getElementById('msgPanel').scrollTop = 
                document.getElementById('msgPanel').scrollHeight;
                }
            }
        }
    } 
  • Users can communicate through the current window.

    The recipient can type in a message to reply back using the same window. The pop-up window has the screen Chat.aspx, which has the Chat.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 communicates 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.

    User can type in HTML tags also to send messages with different fonts and size. Here, developers can customize the application to give end users an option to set their own styles by selecting fonts and size drop downs. Here in the below screenshot, I am typing the font color and size.

    Chat_fonts.jpg - Click to enlarge image

  • A single user can communicate with multiple users at a time.

    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.

    multi_browser.jpg - Click to enlarge image

Steps to Configure in Your Website

  • Create a new website or open your ASP.NET project in which you want to add the chat pages.
  • Download the attached zip file, unzip and copy folder 'ChatService' to local drive. Configure a virtual directory/Application with any name (say 'WCFChatService') in IIS and make it working under .NET 4.0. Check whether http://localhost/<your_service_app_name>/WCFChat.svc and http://localhost/<your_service_app_name>/OnlineUsers.svc are opening the browser. You can test with WCFTestClient (http://msdn.microsoft.com/en-us/library/bb552364.aspx) also.
  • Add service references to both the services in your website.
  • Add reference to Newtonsoft.Json.dll in your website. Get the DLL from 'ChatClient\Bin' if you don't want to download from JSon.Net site.
  • In your website's log-in page, on successful log-in, add the following code to add the user to online users list:
    C#
    OnlineUsersProxy.OnlineUsersServiceClient objOnlineUsers = 
            new OnlineUsersProxy.OnlineUsersServiceClient();
    Member mem = new Member();
    mem.UserId = txtUserID.Text;
    mem.DisplayName = GetDisplayNameById(mem.UserId); //write your own method
    objOnlineUsers.AddOnlineUser(mem);            
    
    //redirect home page
  • Copy Chat.aspx and GetChat.aspx to your website folder and Chat.js and ChatWindow.js files to Scripts subfolder. Copy the below tags for repeater control to your home page where you want to show online users.
  • ASP.NET
    Online users:<br />
        <asp:Repeater ID="rptrOnlineUsers" runat="server">
             <ItemTemplate>                                        
              <span style="cursor:hand;text-decoration:underline;" 
        onclick="OpenChatBox('<%#((OnlineUsersProxy.Member)
        Container.DataItem).UserId%>','<%#((OnlineUsersProxy.Member)
        Container.DataItem).ChatId%>')"><%#((OnlineUsersProxy.Member)
        Container.DataItem).DisplayName%></span><br />
             </ItemTemplate>
        </asp:Repeater><span class="Apple-tab-span" style="white-space: pre; ">    
        </span>   
    <input type="hidden" id="hidCurrentUser" runat="server" /> 
  • Add below code in Page_Load for binding online users to repeater. Here I am saving the current logged in user id in hidden field which is used later in chat.
    C#
    hidCurrentUser.Value = HttpContext.Current.User.Identity.Name;
    
    OnlineUsersProxy.OnlineUsersServiceClient wsOnlineUsers = 
            new OnlineUsersProxy.OnlineUsersServiceClient();
    rptrOnlineUsers.DataSource = wsOnlineUsers.GetOnlineUsers
                (HttpContext.Current.User.Identity.Name);
    rptrOnlineUsers.DataBind(); 
  • Run your project to test ..... :-)

Points of Interest

I hope using WCF and JSon.Net in place of DB will be a better solution, and while improving this, I got a chance to fix issues with other browsers, Firefox and Chrome.

Enhancements

  • WCF service stores the messages in memory and I implemented few methods to free memory by deleting old messages. And user can call these methods on log-out to remove logged out user messages.
  • 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 and to show image of the user as it uses repeater control.
  • I used simple design for chat window and it can be changed to include the time of message and images.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
India India
Hi, I am Narsimlu Keshagouni working as Technical Lead in Hyderabad, India.

Comments and Discussions

 
QuestionStepwise achievement of this nice application you created Pin
Minstrel Prince17-Feb-16 3:44
Minstrel Prince17-Feb-16 3:44 
QuestionHow to configure i have tried my level best but could not please can you reply how to configure this Pin
Malikdanish16-Feb-16 6:24
professionalMalikdanish16-Feb-16 6:24 
QuestionStep wise configure this chat application Pin
chakram0818-May-15 22:48
chakram0818-May-15 22:48 
QuestionWCF chatting Pin
Member 1068140630-May-14 9:02
Member 1068140630-May-14 9:02 
QuestionOnlineUsers method is not refreshing Pin
madhavi_0814-May-14 21:31
madhavi_0814-May-14 21:31 
Questioni don't know how to configure the virtual directory Pin
Member 1008169022-Mar-14 3:53
Member 1008169022-Mar-14 3:53 
QuestionLoad Testing Pin
sachin.vishwa901-Feb-14 2:51
professionalsachin.vishwa901-Feb-14 2:51 
Questionsir please help Pin
shreyasm198317-Dec-13 23:43
shreyasm198317-Dec-13 23:43 
Questionall steps performed getting error after Pin
cyber_addicted12-Nov-13 20:01
cyber_addicted12-Nov-13 20:01 
Generalchatting Pin
aiswarjya19-Aug-13 23:59
aiswarjya19-Aug-13 23:59 
Questionbase address settings Pin
Vinay Kumar Tiwary16-Jun-13 18:14
Vinay Kumar Tiwary16-Jun-13 18:14 
GeneralEasiest way to create and consume WCF Services in asp.net Pin
Lalit24rocks14-May-13 21:47
Lalit24rocks14-May-13 21:47 
QuestionRunning the project localhost howto??? Pin
simpa26-Mar-13 0:16
simpa26-Mar-13 0:16 
AnswerRe: Running the project localhost howto??? Pin
Alfy Geo6-Mar-14 0:35
Alfy Geo6-Mar-14 0:35 
QuestionMessages not going Pin
Member 814812914-Mar-13 1:12
Member 814812914-Mar-13 1:12 
QuestionDon't Know How to configure IIS Plz help me. Pin
Member 876390530-Dec-12 18:02
Member 876390530-Dec-12 18:02 
QuestionCan you plz help me on this ... Pin
blrsimon17-Oct-12 23:47
blrsimon17-Oct-12 23:47 
GeneralRe: Can you plz help me on this ... Pin
Narsimlu Keshagouni8-Nov-12 19:38
professionalNarsimlu Keshagouni8-Nov-12 19:38 
QuestionPlease, help Pin
Mr Dun2-Oct-12 21:10
Mr Dun2-Oct-12 21:10 
BugSending and receiving of messages Pin
Pooja Somasundar1-Aug-12 18:43
Pooja Somasundar1-Aug-12 18:43 
GeneralRe: Sending and receiving of messages Pin
Member 1039243916-Sep-12 6:44
Member 1039243916-Sep-12 6:44 
GeneralRe: Sending and receiving of messages Pin
Narsimlu Keshagouni21-Sep-12 0:06
professionalNarsimlu Keshagouni21-Sep-12 0:06 
QuestionRegarding a minor issue Pin
Pooja Somasundar25-Jul-12 21:00
Pooja Somasundar25-Jul-12 21:00 
AnswerRe: Regarding a minor issue Pin
Narsimlu Keshagouni21-Sep-12 0:08
professionalNarsimlu Keshagouni21-Sep-12 0:08 
Generalfilter users on the default page Pin
martinr8429-Jun-12 8:33
martinr8429-Jun-12 8:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.