简体   繁体   中英

Chat application using signalr as wcf service

i have done the chat application using signalr client and chatsever implemented as class. Now i want to implement chat server as wcf service.

    <link rel="stylesheet" href="Styles/jquery-ui.css" />
    <script src="Scripts/jquery-1.8.2.js"></script>
    <script src="Scripts/jquery-ui.js"></script>
    <script type="text/javascript" src="Scripts/jquery.dialogextend.1_0_1.js"></script>
    <script type="text/javascript" src="Scripts/jquery.signalR.js"></script>
    <script type="text/javascript" src="Scripts/jQuery.tmpl.js"></script>
    <script type="text/javascript" src="signalr/hubs"></script>
    <script id="new-online-contacts" type="text/x-jquery-tmpl">
        <div>
        <ul>
        {{each messageRecipients}}
            <li id="chatLink${messageRecipientId}"><a href="javascript:;" onclick="javascript:SRChat.initiateChat('${messageRecipientId}','${messageRecipientName}');">${messageRecipientName}</a></li>
        {{/each}}
        </ul>
        </div>
    </script>
    <script id="new-chatroom-template" type="text/x-jquery-tmpl">
    <div id="chatRoom${chatRoomId}" class="chatRoom">
        <ul id="messages${chatRoomId}" class="chatMessages">
        </ul>
        <form id="sendmessage${chatRoomId}" action="#">
            <input type="text" id="newmessage${chatRoomId}" class="chatNewMessage"/>
            <div class="clear"></div>
            <input type="button" id="chatsend${chatRoomId}" value="Send" class="chatSend" OnClick="javascript:SRChat.sendChatMessage('${chatRoomId}')" />
            <input type="button" id="chatend${chatRoomId}" value="End Chat" class="chatSend" OnClick="javascript:SRChat.endChat('${chatRoomId}')" />
        </form>
    </div>
    </script>
    <script id="new-chat-header" type="text/x-jquery-tmpl">
    <div id="chatRoomHeader${chatRoomId}">
        {{each messageRecipients}}
            {{if $index == 0}}
                ${messageRecipientName}
            {{else}}
                , ${messageRecipientName}
            {{/if}}
        {{/each}}
    <div>
    </script>
    <script id="new-message-template" type="text/x-jquery-tmpl">
    <li class="message" id="m-${chatMessageId}">
        <strong>${displayPrefix}</strong>
        {{html messageText}}
    </li>
    </script>
    <script id="new-notify-message-template" type="text/x-jquery-tmpl">
    <li class="message" id="m-${chatMessageId}">
        <strong>{{html messageText}}</strong>
    </li>
    </script>
    <script type="text/javascript"> 
    //<![CDATA[

        $(document).ready(function () {

            SRChat.attachEvents();
        });

        SRChat = new function () {
          var  Username = GetParameterValues('Username');
            function GetParameterValues(param) {
                var url = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
                for (var i = 0; i < url.length; i++) {
                    var urlparam = url[i].split('=');
                    if (urlparam[0] == param) {
                        return urlparam[1];
                    }
                }
            }
            var chatRooms = 0;
            var numRand = Username;
            var senderId = numRand;
            var senderName = 'User :' + numRand;

            var sRChatServer;

            window.onbeforeunload = function () {
                if (chatRooms > 0)
                    return "All chat instances will be ended!";
            };

            this.attachEvents = function () {
                $("#userNameLabel").html(senderName);
                if ($.connection != null) {
                    jQuery.support.cors = true;
                    $.connection.hub.url = 'signalr/hubs';
                    sRChatServer = $.connection.sRChatServer;

                    $.connection.hub.start({ transport: 'auto' }, function () {
                        sRChatServer.server.connect(senderId, senderName).fail(function (e) {
                            alert(e);
                        });
                    });

                    sRChatServer.client.initiateChatUI = function (chatRoom) {
                        var chatRoomDiv = $('#chatRoom' + chatRoom.chatRoomId);
                        if (($(chatRoomDiv).length > 0)) {
                            var chatRoomText = $('#newmessage' + chatRoom.chatRoomId);
                            var chatRoomSend = $('#chatsend' + chatRoom.chatRoomId);
                            var chatRoomEndChat = $('#chatend' + chatRoom.chatRoomId);

                            chatRoomText.show();
                            chatRoomSend.show();
                            chatRoomEndChat.show();
                        }
                        else {
                            var e = $('#new-chatroom-template').tmpl(chatRoom);
                            var c = $('#new-chat-header').tmpl(chatRoom);

                            chatRooms++;

                            //dialog options
                            var dialogOptions = {
                                "id": '#messages' + chatRoom.chatRoomId,
                                "title": c,
                                "width": 360,
                                "height": 365,
                                "modal": false,
                                "resizable": false,
                                "close": function () { javascript: SRChat.endChat('' + chatRoom.chatRoomId + ''); $(this).remove(); }
                            };

                            // dialog-extend options
                            var dialogExtendOptions = {
                                "close": true,
                                "maximize": false,
                                "minimize": true,
                                "dblclick": 'minimize',
                                "titlebar": 'transparent'
                            };

                            e.dialog(dialogOptions).dialogExtend(dialogExtendOptions);

                            $('#sendmessage' + chatRoom.chatRoomId).keypress(function (e) {
                                if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
                                    $('#chatsend' + chatRoom.chatRoomId).click();
                                    return false;
                                }
                            });
                        }
                    };

                    sRChatServer.client.updateChatUI = function (chatRoom) {
                        var chatRoomHeader = $('#chatRoomHeader' + chatRoom.chatRoomId);
                        var c = $('#new-chat-header').tmpl(chatRoom);
                        chatRoomHeader.html(c);
                    };

                    sRChatServer.client.receiveChatMessage = function (chatMessage, chatRoom) {
                        sRChatServer.client.initiateChatUI(chatRoom);
                        var chatRoom = $('#chatRoom' + chatMessage.conversationId);
                        var chatRoomMessages = $('#messages' + chatMessage.conversationId);
                        var e = $('#new-message-template').tmpl(chatMessage).appendTo(chatRoomMessages);
                        e[0].scrollIntoView();
                        chatRoom.scrollIntoView();
                    };

                    sRChatServer.client.receiveLeftChatMessage = function (chatMessage) {
                        var chatRoom = $('#chatRoom' + chatMessage.conversationId);
                        var chatRoomMessages = $('#messages' + chatMessage.conversationId);
                        var e = $('#new-notify-message-template').tmpl(chatMessage).appendTo(chatRoomMessages);
                        e[0].scrollIntoView();
                        chatRoom.scrollIntoView();
                    };

                    sRChatServer.client.receiveEndChatMessage = function (chatMessage) {
                        var chatRoom = $('#chatRoom' + chatMessage.conversationId);
                        var chatRoomMessages = $('#messages' + chatMessage.conversationId);
                        var chatRoomText = $('#newmessage' + chatMessage.conversationId);
                        var chatRoomSend = $('#chatsend' + chatMessage.conversationId);
                        var chatRoomEndChat = $('#chatend' + chatMessage.conversationId);

                        chatRooms--;

                        var e = $('#new-notify-message-template').tmpl(chatMessage).appendTo(chatRoomMessages);

                        chatRoomText.hide();
                        chatRoomSend.hide();
                        chatRoomEndChat.hide();

                        e[0].scrollIntoView();
                        chatRoom.scrollIntoView();
                    };

                    sRChatServer.client.onGetOnlineContacts = function (chatUsers) {
                        var e = $('#new-online-contacts').tmpl(chatUsers);
                        var chatLink = $('#chatLink' + senderId);
                        e.find("#chatLink" + senderId).remove();
                        $("#chatOnlineContacts").html("");
                        $("#chatOnlineContacts").html(e);
                    };
                }
            };

            this.sendChatMessage = function (chatRoomId) {
                var chatRoomNewMessage = $('#newmessage' + chatRoomId);

                if (chatRoomNewMessage.val() == null || chatRoomNewMessage.val() == "")
                    return;

                var chatMessage = {
                    senderId: senderId,
                    senderName: senderName,
                    conversationId: chatRoomId,
                    messageText: chatRoomNewMessage.val()
                };

                chatRoomNewMessage.val('');
                chatRoomNewMessage.focus();
                sRChatServer.server.sendChatMessage(chatMessage).fail(function (e) {
                    alert(e);
                });

                return false;
            };

            this.endChat = function (chatRoomId) {
                var chatRoomNewMessage = $('#newmessage' + chatRoomId);

                var chatMessage = {
                    senderId: senderId,
                    senderName: senderName,
                    conversationId: chatRoomId,
                    messageText: chatRoomNewMessage.val()
                };
                chatRoomNewMessage.val('');
                chatRoomNewMessage.focus();
                sRChatServer.server.endChat(chatMessage).fail(function (e) {
                    //alert(e);
                });
            };

            this.initiateChat = function (toUserId, toUserName) {
                if (sRChatServer == null) {
                    alert("Problem in connecting to Chat Server. Please Contact Administrator!");
                    return;
                }
                sRChatServer.server.initiateChat(senderId, senderName, toUserId, toUserName).fail(function (e) {
                    alert(e);
                });
            };

        };
    //]]> 
    </script>
</head>
<body>
    <form id="form1" runat="server">

    <div>

        <div id="userNameLabel">
        </div>
        <br />
        <br />
        <div id="chatRooms">
        </div>
        <div id="chatOnlineContacts">
        </div>
    </div>
    </form>
</body>

My server side code is

using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using SignalR.Hubs;

namespace SRChat
{
    [HubName("sRChatServer")]
    public class SRChatServer:Hub

    {
        #region Private Variables
        private static readonly ConcurrentDictionary<string, MessageRecipient> _chatUsers = new ConcurrentDictionary<string, MessageRecipient>(StringComparer.OrdinalIgnoreCase);
        private static readonly ConcurrentDictionary<string, ChatRoom> _chatRooms = new ConcurrentDictionary<string, ChatRoom>(StringComparer.OrdinalIgnoreCase);
        #endregion

        #region Public Methods

        public bool Connect(string userId, string userName)
        {
            try
            {
                if (string.IsNullOrEmpty(userId) | string.IsNullOrEmpty(userName))
                {
                    return false;
                }
                if (GetChatUserByUserId(userId) == null)
                {
                    AddUser(userId, userName);
                }
                else
                {
                    ModifyUser(userId, userName);
                }
                SendOnlineContacts();
                return true;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Problem in connecting to chat server!");
            }
        }
        public override Task Disconnect()
        {
            try
            {
                DeleteUser(Context.ConnectionId);
                return null;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Problem in disconnecting from chat server!");
            }
        }
        public bool InitiateChat(string fromUserId, string fromUserName, string toUserId, string toUserName)
        {
            try
            {
                if (string.IsNullOrEmpty(fromUserId) || string.IsNullOrEmpty(fromUserName) || string.IsNullOrEmpty(toUserId) || string.IsNullOrEmpty(toUserName))
                {
                    return false;
                }

                var fromUser = GetChatUserByUserId(fromUserId);
                var toUser = GetChatUserByUserId(toUserId);

                if (fromUser != null && toUser != null)
                {
                    if (!CheckIfRoomExists(fromUser, toUser))
                    {
                        //Create New Chat Room
                        ChatRoom chatRoom = new ChatRoom();
                        chatRoom.chatRoomInitiatedBy = fromUser.messageRecipientId;
                        chatRoom.chatRoomInitiatedTo = toUser.messageRecipientId;

                        chatRoom.messageRecipients.Add(fromUser);
                        chatRoom.messageRecipients.Add(toUser);

                        //create and save blank message to get new conversation id
                        ChatMessage chatMessage = new ChatMessage();
                        chatMessage.messageText = "Chat Initiated";
                        chatMessage.senderId = fromUser.messageRecipientId;
                        chatMessage.senderName = fromUser.messageRecipientName;

                        fromUser.chatRoomIds.Add(chatRoom.chatRoomId);
                        toUser.chatRoomIds.Add(chatRoom.chatRoomId);

                        //Create SignalR Group for this chat room and add users connection to it
                        Groups.Add(fromUser.connectionId, chatRoom.chatRoomId);
                        Groups.Add(toUser.connectionId, chatRoom.chatRoomId);

                        //Add Chat room object to collection
                        if (_chatRooms.TryAdd(chatRoom.chatRoomId, chatRoom))
                        {
                            //Generate Client UI for this room
                            Clients[fromUser.connectionId].initiateChatUI(chatRoom);
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Problem in starting chat!");
            }
        }
        public bool EndChat(ChatMessage chatMessage)
        {
            try
            {
                ChatRoom chatRoom;
                if (_chatRooms.TryGetValue(chatMessage.conversationId, out chatRoom))
                {
                    if (_chatRooms[chatRoom.chatRoomId].chatRoomInitiatedBy == chatMessage.senderId)
                    {
                        chatMessage.messageText = string.Format("{0} left the chat. Chat Ended!", chatMessage.senderName);
                        if (_chatRooms.TryRemove(chatRoom.chatRoomId, out chatRoom))
                        {
                            Clients[chatRoom.chatRoomId].receiveEndChatMessage(chatMessage);
                            foreach (MessageRecipient messageReceipient in chatRoom.messageRecipients)
                            {
                                if (messageReceipient.chatRoomIds.Contains(chatRoom.chatRoomId))
                                {
                                    messageReceipient.chatRoomIds.Remove(chatRoom.chatRoomId);
                                    Groups.Remove(messageReceipient.connectionId, chatRoom.chatRoomId);
                                }
                            }
                        }
                    }
                    else
                    {
                        MessageRecipient messageRecipient = GetChatUserByUserId(chatMessage.senderId);
                        if (messageRecipient != null && messageRecipient.chatRoomIds.Contains(chatRoom.chatRoomId))
                        {
                            chatRoom.messageRecipients.Remove(messageRecipient);
                            messageRecipient.chatRoomIds.Remove(chatRoom.chatRoomId);
                            if (chatRoom.messageRecipients.Count < 2)
                            {
                                chatMessage.messageText = string.Format("{0} left the chat. Chat Ended!", chatMessage.senderName);
                                if (_chatRooms.TryRemove(chatRoom.chatRoomId, out chatRoom))
                                {
                                    Clients[chatRoom.chatRoomId].receiveEndChatMessage(chatMessage);
                                    foreach (MessageRecipient messageReceipient in chatRoom.messageRecipients)
                                    {
                                        if (messageReceipient.chatRoomIds.Contains(chatRoom.chatRoomId))
                                        {
                                            messageReceipient.chatRoomIds.Remove(chatRoom.chatRoomId);
                                            Groups.Remove(messageReceipient.connectionId, chatRoom.chatRoomId);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                chatMessage.messageText = string.Format("{0} left the chat.", chatMessage.senderName);
                                Groups.Remove(messageRecipient.connectionId, chatRoom.chatRoomId);
                                Clients[messageRecipient.connectionId].receiveEndChatMessage(chatMessage);
                                Clients[chatRoom.chatRoomId].receiveLeftChatMessage(chatMessage);
                                Clients[chatRoom.chatRoomId].updateChatUI(chatRoom);
                            }
                        }
                    }
                }
                else
                {
                    throw new InvalidOperationException("Problem in ending chat!");
                }
                return true;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Problem in ending chat!");
            }
        }
        public bool SendChatMessage(ChatMessage chatMessage)
        {
            try
            {
                ChatRoom chatRoom;
                if (_chatRooms.TryGetValue(chatMessage.conversationId, out chatRoom))
                {
                    chatMessage.chatMessageId = Guid.NewGuid().ToString();
                    chatMessage.timestamp = DateTime.Now;
                    Clients[chatMessage.conversationId].receiveChatMessage(chatMessage, chatRoom);
                    return true;
                }
                else
                {
                    throw new InvalidOperationException("Problem in sending message!");
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Problem in sending message!");
            }
        }
        private bool SendOnlineContacts()
        {
            try
            {
                OnlineContacts onlineContacts = new OnlineContacts();
                foreach (var item in _chatUsers)
                {
                    onlineContacts.messageRecipients.Add(item.Value);
                }
                Clients.onGetOnlineContacts(onlineContacts);
                return false;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Problem in getting contacts!");
            }
        }

        #endregion

        #region Private Methods

        private Boolean CheckIfRoomExists(MessageRecipient fromUser, MessageRecipient toUser)
        {
            foreach (string chatRoomId in fromUser.chatRoomIds)
            {
                Int32 count = (from mr in _chatRooms[chatRoomId].messageRecipients
                               where mr.messageRecipientId == toUser.messageRecipientId
                               select mr).Count();
                if (count > 0)
                {
                    return true;
                }
            }
            foreach (string chatRoomId in toUser.chatRoomIds)
            {
                Int32 count = (from mr in _chatRooms[chatRoomId].messageRecipients
                               where mr.messageRecipientId == fromUser.messageRecipientId
                               select mr).Count();
                if (count > 0)
                {
                    return true;
                }
            }
            return false;
        }
        private MessageRecipient AddUser(string userId, string userName)
        {
            var user = new MessageRecipient();
            user.messageRecipientId = userId;
            user.messageRecipientName = userName;
            user.connectionId = Context.ConnectionId;
            _chatUsers[userId] = user;
            return user;
        }
        private MessageRecipient ModifyUser(string userId, string userName)
        {
            var user = GetChatUserByUserId(userId);
            user.messageRecipientName = userName;
            user.connectionId = Context.ConnectionId;
            _chatUsers[userId] = user;
            return user;
        }
        private Boolean DeleteUser(string userId, string userName)
        {
            var user = GetChatUserByUserId(userId);
            if (user != null && _chatUsers.ContainsKey(user.messageRecipientId))
            {
                MessageRecipient messageRecipient;
                return _chatUsers.TryRemove(user.messageRecipientId, out messageRecipient);
            }
            return false;
        }
        private Boolean DeleteUser(string connectionId)
        {
            var returnValue = false;
            var user = GetChatUserByConnectionId(connectionId);
            if (user != null && _chatUsers.ContainsKey(user.messageRecipientId))
            {
                MessageRecipient messageRecipient;
                returnValue = _chatUsers.TryRemove(user.messageRecipientId, out messageRecipient);

                //remoave from all groups and chatrooms
                foreach (string chatRoomId in messageRecipient.chatRoomIds)
                {
                    _chatRooms[chatRoomId].messageRecipients.Remove(messageRecipient);

                    Groups.Remove(messageRecipient.connectionId, chatRoomId);

                    //notify user left chat
                    ChatMessage chatMessage = new ChatMessage();
                    chatMessage.conversationId = chatRoomId;
                    chatMessage.senderId = messageRecipient.messageRecipientId;
                    chatMessage.senderName = messageRecipient.messageRecipientName;
                    if (_chatRooms[chatRoomId].chatRoomInitiatedBy == messageRecipient.messageRecipientId)
                    {
                        chatMessage.messageText = string.Format("{0} left the chat. Chat Ended!", messageRecipient.messageRecipientName);
                        ChatRoom chatRoom;

                        if (_chatRooms.TryRemove(chatRoomId, out chatRoom))
                        {
                            foreach (MessageRecipient messageReceipient in chatRoom.messageRecipients)
                            {
                                if (messageReceipient.chatRoomIds.Contains(chatRoomId))
                                {
                                    messageReceipient.chatRoomIds.Remove(chatRoomId);
                                }
                            }
                            Clients[chatRoomId].receiveEndChatMessage(chatMessage);
                        }
                    }
                    else
                    {
                        if (_chatRooms[chatRoomId].messageRecipients.Count() < 2)
                        {
                            chatMessage.messageText = string.Format("{0} left the chat. Chat Ended!", messageRecipient.messageRecipientName);
                            ChatRoom chatRoom;
                            if (_chatRooms.TryRemove(chatRoomId, out chatRoom))
                            {
                                foreach (MessageRecipient messageReceipient in chatRoom.messageRecipients)
                                {
                                    if (messageReceipient.chatRoomIds.Contains(chatRoomId))
                                    {
                                        messageReceipient.chatRoomIds.Remove(chatRoomId);
                                    }
                                }
                                Clients[chatRoomId].receiveEndChatMessage(chatMessage);
                            }
                        }
                        else
                        {
                            chatMessage.messageText = string.Format("{0} left the chat.", messageRecipient.messageRecipientName);
                            Clients[chatRoomId].receiveLeftChatMessage(chatMessage);
                        }
                    }
                }
            }
            return returnValue;
        }
        private MessageRecipient GetChatUserByUserId(string userId)
        {
            return _chatUsers.Values.FirstOrDefault(u => u.messageRecipientId == userId);
        }
        private MessageRecipient GetChatUserByConnectionId(string connectionId)
        {
            return _chatUsers.Values.FirstOrDefault(u => u.connectionId == connectionId);
        }

        #endregion
    }
}

i want to implement this one as wcf service or web service. please help me in advance

I think the best way to achieve that is to create a windows managed service.(Cause you can't control the lifetime of your service when hosted in IIS with a per-call configuration).

So you should create a new windows service and host both your wcf service and signalr (it's only an idea but I think the code can looks like that):

public class HostWindowService : ServiceBase
{
    public ServiceHost serviceHost = null;
    public HostWindowService()
    {      
        ServiceName = "WCFWindowsServiceSample";
    }

    public static void Main()
    {
        ServiceBase.Run(new HostWindowService());
    }

    protected override void OnStart(string[] args)
    {
        //host wcf service
        if (serviceHost != null)
        {
            serviceHost.Close();
        }                   
        serviceHost = new ServiceHost(typeof(WCFService));    
        serviceHost.Open();

        //host signalr
        Task.Run(() => SignalRHost());                  
    }

    private void SignalRHost()
    {
        try
        {
            SignalR = WebApp.Start("http://localhost:8080");
        }
        catch (TargetInvocationException)
        {
            WriteToConsole("A server is already running at " + "http://localhost:8080");        
            return;
        }       
    }

    class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(CorsOptions.AllowAll);
            app.MapSignalR();
        }
    }       

    protected override void OnStop()
    {
        if (serviceHost != null)
        {
            serviceHost.Close();
            serviceHost = null;
        }
    }
}

References : How to: Host a WCF Service in a Managed Windows Service and Self-Hosting SignalR in a Windows Service

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM