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

   11 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. 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
  7. Hello bro..i wnt to save messages in database using this code plz help me

    ReplyDelete

  • Popular Posts
  • Comments