Click here to Skip to main content
15,868,340 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

 
GeneralRe: filter users on the default page Pin
Narsimlu Keshagouni2-Jul-12 23:29
professionalNarsimlu Keshagouni2-Jul-12 23:29 
Questionplease reply for this error Pin
jagadeesh3111-May-12 16:12
jagadeesh3111-May-12 16:12 
AnswerRe: please reply for this error Pin
Narsimlu Keshagouni14-May-12 0:43
professionalNarsimlu Keshagouni14-May-12 0:43 
QuestionPlease help Me Pin
jpr chaitanya27-Apr-12 1:18
jpr chaitanya27-Apr-12 1:18 
when the pop Up window is Minimized,
The popup chat window to flash blinking color(orange) like the way Yahoo, Google, MSN instant messengers do. pls give me any suggestion about code
AnswerRe: Please help Me Pin
Narsimlu Keshagouni27-Apr-12 18:54
professionalNarsimlu Keshagouni27-Apr-12 18:54 
GeneralRe: Please help Me Pin
jpr chaitanya29-Apr-12 18:08
jpr chaitanya29-Apr-12 18:08 
QuestionRegards WCF service in local host Pin
manojprabakaran12-Apr-12 13:12
manojprabakaran12-Apr-12 13:12 
Questionplz help me it gives an error. Pin
Member 788745527-Mar-12 22:16
Member 788745527-Mar-12 22:16 
AnswerRe: plz help me it gives an error. Pin
Narsimlu Keshagouni3-Apr-12 3:24
professionalNarsimlu Keshagouni3-Apr-12 3:24 
QuestionASP.NET Chatting using WCF Services and JSon Pin
Member 875383424-Mar-12 21:27
Member 875383424-Mar-12 21:27 
AnswerRe: ASP.NET Chatting using WCF Services and JSon Pin
Narsimlu Keshagouni27-Mar-12 14:45
professionalNarsimlu Keshagouni27-Mar-12 14:45 
QuestionNotifying the user. Pin
butters198222-Mar-12 5:34
butters198222-Mar-12 5:34 
AnswerRe: Notifying the user. Pin
Narsimlu Keshagouni27-Mar-12 14:49
professionalNarsimlu Keshagouni27-Mar-12 14:49 
GeneralRe: Notifying the user. Pin
butters19829-Apr-12 9:44
butters19829-Apr-12 9:44 
GeneralRe: Notifying the user. Pin
jpr chaitanya30-Apr-12 0:05
jpr chaitanya30-Apr-12 0:05 
GeneralRe: Notifying the user. Pin
jpr chaitanya27-Apr-12 1:31
jpr chaitanya27-Apr-12 1:31 
GeneralHelp on the Article "ASP.NET Chatting using WCF Services and JSon" Pin
Deepak1414141415-Mar-12 20:58
Deepak1414141415-Mar-12 20:58 
GeneralRe: Help on the Article "ASP.NET Chatting using WCF Services and JSon" Pin
Narsimlu Keshagouni15-Mar-12 22:13
professionalNarsimlu Keshagouni15-Mar-12 22:13 
QuestionImports WCFChatProxy Pin
John Windsor13-Dec-11 12:45
John Windsor13-Dec-11 12:45 
AnswerRe: Imports WCFChatProxy Pin
Narsimlu Keshagouni15-Dec-11 17:44
professionalNarsimlu Keshagouni15-Dec-11 17:44 
Suggestionfeature set Pin
MacSpudster6-Dec-11 12:21
professionalMacSpudster6-Dec-11 12:21 
GeneralRe: feature set Pin
Narsimlu Keshagouni7-Dec-11 0:50
professionalNarsimlu Keshagouni7-Dec-11 0:50 
GeneralRe: feature set Pin
kishorebt27-May-14 19:21
kishorebt27-May-14 19:21 
GeneralRe: feature set Pin
kishorebt27-May-14 21:41
kishorebt27-May-14 21:41 
GeneralMy vote of 5 Pin
Monjurul Habib2-Dec-11 4:47
professionalMonjurul Habib2-Dec-11 4:47 

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.