AspBucket offers ASP.NET, C#, VB, Jquery, CSS, Ajax, SQL tutorials. It is the best place for programmers to learn

Monday, 7 March 2016

Implement of private one to one chat between database table users with SignalR

In this blog I will discuss How Implement of private one to one chat between database table users with SignalR?  SignalR is used for real time communication in ASP.NET.  I will create separate user control for chat application. Please check below How to I implement it.

Step 1: Install SignalR  from nuget to application.
 Tools>Library Package Manager>Package Manager Console

Type following command in Manager Console: Install-Package Microsoft.AspNet.SignalR

SignalR will added in reference also

Step 2: Add ChatHub, MessageDetail & UserDetail Classes

    public class MessageDetail
    {
        public int FromUserID { get; set; }
        public string FromUserName { get; set; }
        public int ToUserID { get; set; }
        public string ToUserName { get; set; }       
        public string Message { get; set; }
    }

    public class UserDetail
    {
        public string ConnectionId { get; set; }
        public int UserID { get; set; }
        public string UserName { get; set; }
    }

    [HubName("chatHub")]
    public class ChatHub : Hub
    {
        #region---Data Members---
        static List<UserDetail> ConnectedUsers = new List<UserDetail>();
        static List<MessageDetail> CurrentMessage = new List<MessageDetail>();
        #endregion

        #region---Methods---
        public void Connect(string UserName, int UserID)
        {
            var id = Context.ConnectionId;

            if (ConnectedUsers.Count(x => x.ConnectionId == id) == 0)
            {
                ConnectedUsers.Add(new UserDetail { ConnectionId = id, UserName = UserName + "-" + UserID, UserID = UserID });
            }
            UserDetail CurrentUser = ConnectedUsers.Where(u => u.ConnectionId == id).FirstOrDefault();
            // send to caller           
            Clients.Caller.onConnected(CurrentUser.UserID.ToString(), CurrentUser.UserName, ConnectedUsers, CurrentMessage, CurrentUser.UserID);
            // send to all except caller client           
            Clients.AllExcept(CurrentUser.ConnectionId).onNewUserConnected(CurrentUser.UserID.ToString(), CurrentUser.UserName, CurrentUser.UserID);
        }

        public void SendMessageToAll(string userName, string message)
        {
            // store last 100 messages in cache
            //AddMessageinCache(userName, message);

            // Broad cast message
            //Clients.All.messageReceived(userName, message);
        }

        public void SendPrivateMessage(string toUserId, string message)
        {
            try
            {
                string fromconnectionid = Context.ConnectionId;
                string strfromUserId = (ConnectedUsers.Where(u => u.ConnectionId == Context.ConnectionId).Select(u => u.UserID).FirstOrDefault()).ToString();
                int _fromUserId = 0;
                int.TryParse(strfromUserId, out _fromUserId);
                int _toUserId = 0;
                int.TryParse(toUserId, out _toUserId);
                List<UserDetail> FromUsers = ConnectedUsers.Where(u => u.UserID == _fromUserId).ToList();
                List<UserDetail> ToUsers = ConnectedUsers.Where(x => x.UserID == _toUserId).ToList();

                if (FromUsers.Count != 0 && ToUsers.Count() != 0)
                {
                    foreach (var ToUser in ToUsers)
                    {
                        // send to                                                                                            //Chat Title
                        Clients.Client(ToUser.ConnectionId).sendPrivateMessage(_fromUserId.ToString(), FromUsers[0].UserName, FromUsers[0].UserName, message);
                    }


                    foreach (var FromUser in FromUsers)
                    {
                        // send to caller user                                                                                //Chat Title
                        Clients.Client(FromUser.ConnectionId).sendPrivateMessage(_toUserId.ToString(), FromUsers[0].UserName, ToUsers[0].UserName, message);
                    }
                    // send to caller user
                    //Clients.Caller.sendPrivateMessage(_toUserId.ToString(), FromUsers[0].UserName, message);
                    //ChatDB.Instance.SaveChatHistory(_fromUserId, _toUserId, message);
                    MessageDetail _MessageDeail = new MessageDetail { FromUserID = _fromUserId, FromUserName = FromUsers[0].UserName, ToUserID = _toUserId, ToUserName = ToUsers[0].UserName, Message = message };
                    AddMessageinCache(_MessageDeail);
                }
            }
            catch { }
        }

        public void RequestLastMessage(int FromUserID, int ToUserID)
        {
            List<MessageDetail> CurrentChatMessages = (from u in CurrentMessage where ((u.FromUserID == FromUserID && u.ToUserID == ToUserID) || (u.FromUserID == ToUserID && u.ToUserID == FromUserID)) select u).ToList();
            //send to caller user
            Clients.Caller.GetLastMessages(ToUserID, CurrentChatMessages);
        }

        public void SendUserTypingRequest(string toUserId)
        {
            string strfromUserId = (ConnectedUsers.Where(u => u.ConnectionId == Context.ConnectionId).Select(u => u.UserID).FirstOrDefault()).ToString();
        
            int _toUserId = 0;
            int.TryParse(toUserId, out _toUserId);
            List<UserDetail> ToUsers = ConnectedUsers.Where(x => x.UserID == _toUserId).ToList();

            foreach (var ToUser in ToUsers)
            {
                // send to                                                                                            
                Clients.Client(ToUser.ConnectionId).ReceiveTypingRequest(strfromUserId);
            }
        }

        public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
        {
            var item = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
            if (item != null)
            {
                ConnectedUsers.Remove(item);
                if (ConnectedUsers.Where(u => u.UserID == item.UserID).Count() == 0)
                {
                    var id = item.UserID.ToString();
                    Clients.All.onUserDisconnected(id, item.UserName);
                }
            }
            return base.OnDisconnected(stopCalled);
        }
        #endregion

        #region---private Messages---
        private void AddMessageinCache(MessageDetail _MessageDetail)
        {
            CurrentMessage.Add(_MessageDetail);
            if (CurrentMessage.Count > 100)
                CurrentMessage.RemoveAt(0);
        }
        #endregion
    }

Register SignarR on Startup Class
[assembly: OwinStartup(typeof(MyProject.Chat.Startup))]
namespace MyProject.Chat
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

Step 3: I am using jQuery UI Chatbox Plugin(http://magma.cs.uiuc.edu/wenpu1/chatbox.html) in project
Github source code(https://github.com/dexterpu/jquery.ui.chatbox)
Give reference of css & js file of Jquery Chat Box Plugin. It will start working.

Step 4: Add notify.mp3 in directory which will play on message alert.

Step 5: Add chatboxManager.js file in project.
var chatHub = $.connection.chatHub;
$(document).ready(function () {
    $('<audio id="chatAudio"><source src="' + srp + 'images/notify.ogg" type="audio/ogg"><source src="' + srp + 'images/notify.mp3" type="audio/mpeg"><source src="' + srp + 'images/notify.wav" type="audio/wav"></audio>').appendTo('body');
    // Declare a proxy to reference the hub. 
    var chatHub = $.connection.chatHub;
    registerClientMethods(chatHub);
    // Start Hub
    $.connection.hub.start().done(function () {
        registerEvents(chatHub);
    });

    $("#chat_min_button").click(function () {
        if ($(this).html() == "<i class=\"fa fa-minus-square\"></i>") {
            $(this).html("<i class=\"fa fa-plus-square\"></i>");
        }
        else {
            $(this).html("<i class=\"fa fa-minus-square\"></i>");
        }
        $("#chat_box").slideToggle();
    });

    setInterval(ResetTypingFlag, 6000);
});


function registerEvents(chatHub) {
    var UserName = $("[id$=hdnCurrentUserName]").val();
    var UserID = parseInt($("[id$=hdnCurrentUserID]").val());
    chatHub.server.connect(UserName, UserID);
}

function registerClientMethods(chatHub) {
    // Calls when user successfully logged in
    chatHub.client.onConnected = function (id, userName, allUsers, messages, userid) {
        $('#hdId').val(id);
        $('#hdUserName').val(userName);

        // Add All Users
        for (i = 0; i < allUsers.length; i++) {
            //AddUser(chatHub, allUsers[i].ConnectionId, allUsers[i].UserName, userid);
            AddUser(chatHub, allUsers[i].UserID, allUsers[i].UserName, userid);
        }

        // Add Existing Messages
        for (i = 0; i < messages.length; i++) {
            AddMessage(messages[i].UserName, messages[i].Message);
        }

    }
}

// On New User Connected
chatHub.client.onNewUserConnected = function (id, name, userid) {
    AddUser(chatHub, id, name, userid);
}

// On User Disconnected
chatHub.client.onUserDisconnected = function (id, userName) {
    $('#' + id).remove();

    //var ctrId = 'private_' + id;
    //$('#' + ctrId).remove();
}

chatHub.client.messageReceived = function (userName, message) {
    AddMessage(userName, message);
}


chatHub.client.sendPrivateMessage = function (windowId, fromUserName, chatTitle, message) {
    var ctrId = 'private_' + windowId;
    if ($('#' + ctrId).length == 0) {
        createPrivateChatWindow(chatHub, windowId, ctrId, fromUserName, chatTitle);
        $('#chatAudio')[0].play();
    }
    else {
        var rType = CheckHiddenWindow();
        if ($('#' + ctrId).parent().css('display') == "none") {
            $('#' + ctrId).parent().parent().effect("shake", { times: 2 }, 1000);
            rType = true;
        }
        if (rType == true) {
            $('#chatAudio')[0].play();
        }
    }
    $('#' + ctrId).chatbox("option", "boxManager").addMsg(fromUserName, message);
    $('#typing_' + windowId).hide();
}

chatHub.client.GetLastMessages = function (TouserID, CurrentChatMessages) {
    //debugger;
    var ctrId = 'private_' + TouserID;
    var AllmsgHtml = "";
    for (i = 0; i < CurrentChatMessages.length; i++) {
        AllmsgHtml += "<div style=\"display: block; max-width: 200px;\" class=\"ui-chatbox-msg\">";
        if (i == CurrentChatMessages.length - 1) {
            if ($('#' + ctrId).children().last().html() != "<b>" + CurrentChatMessages[i].FromUserName + ": </b><span>" + CurrentChatMessages[i].Message + "</span>") {
                AllmsgHtml += "<b>" + CurrentChatMessages[i].FromUserName + ": </b><span>" + CurrentChatMessages[i].Message + "</span>";
            }
        }
        else {
            AllmsgHtml += "<b>" + CurrentChatMessages[i].FromUserName + ": </b><span>" + CurrentChatMessages[i].Message + "</span>";
        }
        AllmsgHtml += "</div>";
    }
    $('#' + ctrId).prepend(AllmsgHtml);
}

function CheckHiddenWindow() {
    var hidden, state;

    if (typeof document.hidden !== "undefined") {
        state = "visibilityState";
    } else if (typeof document.mozHidden !== "undefined") {
        state = "mozVisibilityState";
    } else if (typeof document.msHidden !== "undefined") {
        state = "msVisibilityState";
    } else if (typeof document.webkitHidden !== "undefined") {
        state = "webkitVisibilityState";
    }

    if (document[state] == "hidden")
        return true;
    else
        return false;

}

function AddUser(chatHub, id, name, userid) {
    var currentuserid = parseInt($("[id$=hdnCurrentUserID]").val());
    var connectionid = $('#hdId').val();
    var code = "";
    if (connectionid == "") {
        if (userid == currentuserid) {
            $('#hdId').val(id);
            connectionid = id;
            $('#hdUserName').val(name);
        }
    }
    if (connectionid != id) {
        if ($('#' + id).length == 0) {
            code = $('<a id="' + id + '" class="col-sm-12 bg-success" > <i class=\"fa fa-user\"></i> ' + name + '<a>');
            $(code).dblclick(function () {
                var id = $(this).attr('id');
                if (connectionid != id) {
                    OpenPrivateChatWindow(chatHub, id, name);
                }
            });
        }
    }
    else {
        if ($('#curruser_' + id).length == 0) {
            code = $('<div id="curruser_' + id + '" class="col-sm-12 bg-info"  ><i class=\"fa fa-user\"></i> ' + name + '<div>');

        }
    }
    $("#chat_box").append(code);
}

function OpenPrivateChatWindow(chatHub, id, userName) {
    var ctrId = 'private_' + id;
    if ($('#' + ctrId).length > 0) return;
    createPrivateChatWindow(chatHub, id, ctrId, userName, userName);
}

function createPrivateChatWindow(chatHub, userId, ctrId, userName, chatTitle) {
    $("#chat_div").append("<div id=\"" + ctrId + "\"></div>")
    showList.push(ctrId);
    $('#' + ctrId).chatbox({
        id: ctrId,
        title: chatTitle,
        user: userName,
        offset: getNextOffset(),
        width: 200,
        messageSent: function (id, user, msg) {
            chatHub.server.sendPrivateMessage(userId, msg);
            TypingFlag = true;
        },
        boxClosed: function (removeid) {
            $('#' + removeid).remove();
            var idx = showList.indexOf(removeid);
            if (idx != -1) {
                showList.splice(idx, 1);
                diff = config.width + config.gap;
                for (var i = idx; i < showList.length; i++) {
                    offset = $("#" + showList[i]).chatbox("option", "offset");
                    $("#" + showList[i]).chatbox("option", "offset", offset - diff);
                }
            }
        }

    });
    $('#' + ctrId).siblings().css("position", "relative");
    $('#' + ctrId).siblings().append("<div id=\"typing_" + userId + "\" style=\"width:20px; height:20px; display:none; position:absolute; right:14px; top:8px\"><img height=\"20\" src=\"" + srp + "images/pencil.gif\" /></div>");
    $('#' + ctrId).siblings().find('textarea').on('input', function (e) {
        if (TypingFlag == true) {
            chatHub.server.sendUserTypingRequest(userId);
        }
        TypingFlag = false;
    });

    var FromUserID = parseInt($("[id$=hdnCurrentUserID]").val());
    var ToUserID = userId;
    chatHub.server.requestLastMessage(FromUserID, ToUserID);
}

chatHub.client.ReceiveTypingRequest = function (userId) {
    var ctrId = 'private_' + userId;
    if ($('#' + ctrId).length > 0) {
        jQuery('#typing_' + userId).show();
        jQuery('#typing_' + userId).delay(6000).fadeOut("slow");
    }
}

// list of boxes shown on the page
var showList = new Array();
var config = {
    width: 200, //px
    gap: 20,
    maxBoxes: 5
};

var getNextOffset = function () {
    return (config.width + config.gap) * showList.length;
};

var TypingFlag = true;

function ResetTypingFlag() {
    TypingFlag = true;
}

function AddMessage(userName, message) {
    //$('#divChatWindow').append('<div class="message"><span class="userName">' + userName + '</span>: ' + message + '</div>');
    //var height = $('#divChatWindow')[0].scrollHeight;
    //$('#divChatWindow').scrollTop(height);
}

Step 6: Add new Web User Control
Right click on solution> Add New Item> Select Web User Control
I renamed it to ctlChatBox.ascx

Add following code in user control.
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ctlChatBox.ascx.cs" Inherits="controls_ctlChatBox" %>
<div id="chat_widnow">
    <div id="chat_title_bar"> <span class="col-sm-9 text-primary"><strong>Online Users</strong></span>
        <div id="chat_min_button"><i class="fa fa-plus-square"></i></div>
    </div>
    <div id="chat_box" style="display: none;overflow-y:auto;">
    </div>
</div>
<div id="chat_div"></div>
<input id="hdId" type="hidden" />
<input id="hdUserName" type="hidden" />
<asp:HiddenField ID="hdnCurrentUserName" runat="server" />
<asp:HiddenField ID="hdnCurrentUserID" runat="server" />
<script src="<%=Page.ResolveUrl("~") %>scripts/jquery.signalR-2.2.0.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="<%=Page.ResolveUrl("~") %>signalr/hubs"></script>
<link href="<%=Page.ResolveUrl("~") %>styles/jquery.ui.chatbox.css" rel="stylesheet" />
<script src="<%=Page.ResolveUrl("~") %>scripts/jquery.ui.chatbox.js"></script>
<script src="<%=Page.ResolveUrl("~") %>scripts/chatboxManager.js"></script>
Add following code in ctlChatBox.ascx.cs
  protected void Page_Load(object sender, EventArgs e)
    {
        hdnCurrentUserName.Value = GetCurrentUserName();
        hdnCurrentUserID.Value = GetCurrentUserID();
    }
That's it run project & Start Chat.

You can download the source code of the application from github.
https://github.com/shivam01990/SignalR-private-one-to-one-chat

   20 comments :

  1. Thanks, that's what I am looking for.

    ReplyDelete
  2. Implementation of this code will be available soon.
    Thanks

    ReplyDelete
    Replies
    1. thanks shivam,
      is it possible to communicate you? I would send you the issue I am facing.

      Delete
  3. Implementation of this is available now.

    ReplyDelete
  4. I want send message offline for user? you can help me! thanks

    ReplyDelete
  5. How can get list user when user offline?

    ReplyDelete
    Replies
    1. Display Offline users & receive Offline messages are not implemented in the current application

      Delete
    2. oh, I need to work with it :(

      Delete
    3. I have problem is change setup status for user

      Delete
  6. hey boys!
    How do I send a message to an offline user in a SignalR chat program? Please hepl me!

    ReplyDelete
    Replies
    1. Hey,
      Have you find out how to send and receive messages to Offline users?

      Delete
  7. Hello bro..i wnt to save messages in database using this code plz help me

    ReplyDelete
  8. can anyone tell me that what is "GetCurrentUserName()" in ctlChatBox.ascx.cs ??

    ReplyDelete
  9. Looking for an MVC version of this project?

    ReplyDelete
    Replies
    1. MVC version is not available but you can integrate it easily.

      Delete
    2. one file is missing in this application...
      that is signalr/hubs this file is missing

      Delete
    3. Please need mvc5 version
      could not integrate it easily

      Delete
    4. I will add MVC version of this project soon.

      Delete
  10. do you already have a MVC version of this , thanks thanks

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete

  • Popular Posts
  • Comments