如何在SignalR聊天程序中向离线用户发送消息?

时间:2016-01-11 15:01:16

标签: javascript c# signalr signalr-hub signalr.client

我在我的网站上使用SignalR进行通信,我需要能够向在线用户以及当前离线的用户发送消息。我在我的项目中成功嵌入了SignalR,除了离线聊天外,一切正常。我不知道为什么这不起作用。

由于我在后台使用Umbraco CMS,因此我可以通过简单的方式访问Umbraco成员的各种ID。因此,他始终具有构建组所需的ID,包括发件人ID和接收者ID。那么,为什么离线聊天仍然不起作用?为什么用户离线时聊天窗口不会打开?

我附上了我的观点和我的中心,我希望有人可以帮助我。

我的ChatHub

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR.Hubs;
using Microsoft.AspNet.SignalR.Transports;
using Microsoft.AspNet.SignalR.Infrastructure;
using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;
using System.Timers;
using Umbraco714.Modal;
using Umbraco.Core;
using Umbraco714.Repositories;
using Umbraco714.Models;
using System.Diagnostics;
using System.Collections;

namespace Umbraco714.Hubs
{
    [HubName("chatHub")]
    public class ChatHub : Hub
    {

        public Task JoinGroup()
        {
            return Groups.Add(Context.ConnectionId, "foo");
        }

        /*
            Method to send a message or a message history to both chat partners in a specific group
        */
        public void Send(string message, string groupName)
        {
            var chatrepo = new ChatRepository();

            if (Clients != null)
            {
                // Call the addMessage method on all clients
                Clients.Group(groupName).addMessage(message, groupName, chatrepo.GetAll(groupName));

                if (chatrepo.GetAll(groupName).Count < 3)
                {
                    var repo = new ChatRepository();
                    repo.Insert(new ChatMessage(message, groupName, DateTime.Now));   
                }
            }
        }

        /*
            Method which notify all existing online users about new user coming online by updating the online users list
        */
        public override Task OnConnected()
        {
            var newUsers = OnlineUser.userObj.Where(item => item.newStatus == true).Select(item => item.userId).ToList();
            UserModal user = OnlineUser.userObj.Where(item => item.sessionId == HttpContext.Current.Request.Cookies["ASP.NET_SessionId"].Value.ToString()).SingleOrDefault();
            user.connectionId = Context.ConnectionId;
            return Clients.All.joined(Context.ConnectionId, newUsers);
        }

        /*
            Method to pass the list of the online users to the newly connected user
        */
        public void GetAllOnlineStatus()
        {
            Clients.Caller.OnlineStatus(Context.ConnectionId, OnlineUser.userObj.Select(item => item.userId).ToList());
        }

        /*
            Method to create a group of any given pair of users 
        */
        public string CreateGroup(string currentUserId, string toConnectTo)
        {
            string strGroupName = GetUniqueGroupName(currentUserId, toConnectTo);
            string connectionId_To = OnlineUser.userObj.Where(item => item.userId == toConnectTo).Select(item => item.connectionId).SingleOrDefault();
            if (!string.IsNullOrEmpty(connectionId_To))
            {
                var chatrepo = new ChatRepository();

                //create the new group with the two member id's
                Groups.Add(Context.ConnectionId, strGroupName);
                Groups.Add(connectionId_To, strGroupName);
                Clients.Caller.setChatWindow(strGroupName, toConnectTo, chatrepo.GetAll(strGroupName));
                return strGroupName;
            }
            return null;
        }

        /*
            Method to create a unique group name 
        */
        private string GetUniqueGroupName(string currentUserId, string toConnectTo)
        {
            return (currentUserId.GetHashCode() ^ toConnectTo.GetHashCode()).ToString();
        }

    }
}

我的聊天视图

@using System;
@using System.Collections.Generic;
@using System.Linq;
@using System.Web;
@using Umbraco714.Models;
@using Umbraco714.Repositories;
@using Umbraco.Core;
@using Umbraco.Core.Persistence;
@using Umbraco.Core.Services;
@using Umbraco.Web.Security;
@using Umbraco.Web;
@using Umbraco.Web.Models;
@using Umbraco.Core.Models;
@using System.Web.Security;


@{

    var memberShipHelper = new Umbraco.Web.Security.MembershipHelper(Umbraco.Web.UmbracoContext.Current);
    var memberId = memberShipHelper.GetCurrentMemberId();
    var member = ApplicationContext.Current.Services.MemberService.GetById(memberId);

}


<div class="container">

    <form id="chatForm">
        <div id="divChatWindow" style="border: 1px solid #3366CC; float: left;  width: 365px; display: none; margin-right: 10px">
            <div id="messageBox" style="border: 1px solid blue;">
                <ul id="messages" style="width: 365px; height: 100px; font: normal 2 verdana; font-size:12px; overflow: auto;  margin-bottom: 0px; word-wrap: break-word;"></ul>

            </div>
            <hr />
            <input type="text" id="msg" class="ChatText" style="width: 280px; height:22px; border-color: #666699; border-style: solid; border-width: 1px; " />
            <input type="button" id="btnChatSend" class="ChatSend" value="Send" style="background-color: #99ccff; font-size: smaller; border: 1px solid #0066FF; height:24px" />
        </div>

        <br />
        <label id="lblUserName" style="font-weight:bold" />
        <br />
        <div id="userList" style="border: thin solid #C0C0C0; font-family: Tunga; width: 150px; font-weight: 500;">

            @foreach (var user in ApplicationContext.Current.Services.MemberService.GetAllMembers().OrderBy(n => n.Name))
            {
                if (@user.Properties["nickname"].Value != null)
                {
                    if (@user.Id != @member.Id)
                    {
                        <img src="~/img/offline.png" data-userid="@user.Id" class="UserImg" width="18" height="18" />
                        <a class="UserItem" data-userid="@user.Id" href="#">@user.Properties["nickname"].Value.ToString()</a>
                        <br />
                    }
                }

            }

        </div>
        <div style="float: left" id="chatContainer">
        </div>
    </form>

    <input type="hidden" id="hdnUserId" value="@ViewData["hdnUserId"]" />
    <input type="hidden" id="hdnUserName" value="@ViewData["hdnUserName"]" />


    <div class="modal fade" id="myModal" tabindex="-1" role="dialog">
        <div class="modal-dialog">
            <div class="modal-content">

                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                    <h4 class="modal-title"></h4>
                </div>
                <div class="modal-body">
                    <
                </div>
                <div class="modal-footer">
                    <input type="hidden" id="ConnectTo" value="0" name="ConnectTo" />
                    <button class="btn btn-default" data-dismiss="modal"></button>
                    <button id="SendRequest" value="SendRequest" name="ButtonId" class="btn btn-primary"></button>
                </div>

            </div><!-- /.modal-content -->
        </div><!-- /.modal-dialog -->
    </div><!-- /.modal -->


</div>


    <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
    <script src="~/signalr/hubs"></script>

    <script type="text/javascript">
        $(document).ready(function () {

            // Proxy created on the fly
            var chat = $.connection.chatHub;

            //Get called from the GetAllOnlineStatus methode in the Chat Hub to pass the online user list to the newly connected user
            chat.client.OnlineStatus = function (connectionId, userList) {

                $("img[id^=stat]").attr('src', 'img/offline.png');
                $(userList).each(function (index, obj) {

                    $("div#userList a[data-userid='" + obj + "']").addClass('online');
                    $("div#userList img[data-userid='" + obj + "']").attr('src', 'img/online.png');

                });
            };

            //Get called from the OnConnected methode in the Chat Hub to update the online user List for existing users
            chat.client.joined = function (connectionId, userList) {
                $(userList).each(function (index, obj) {

                    $("div#userList a[data-userid='" + obj + "']").addClass('online');
                    $("div#userList img[data-userid='" + obj + "']").attr('src', 'img/online.png');

                });
            };

            // make the chat window visible
            chat.client.setChatWindow = function (strGroupName, strChatTo, listMessages) {
                if ($('div[groupname=' + strGroupName + ']').length == 0) {
                    $('div[chatToId=' + strChatTo + ']').attr('groupname', strGroupName);
                    $('div[chatToId=' + strChatTo + ']').css('display', 'block')

                    //load history from SendClient
                    for (var i = 0, l = listMessages.length; i < l; i++) {
                        $('div[groupname=' + strGroupName + ']').find('ul').append('<li>' + listMessages[i].message + '</li>').scrollTop($('html, body').height());
                    }
                }

            };

            // Declare a function on the chat hub so the server can invoke it
            chat.client.addMessage = function (message, groupName, listMessages) {
                if ($('div[groupname=' + groupName + ']').length == 0) {

                    // Load history from the SendClient
                    for (var i = 0, l = listMessages.length; i < l; i++) {
                        $('#divChatWindow').find('#messages').append('<li>' + listMessages[i].message + '</li>');
                    }

                    var chatWindow = $("#divChatWindow").clone(true);
                    $(chatWindow).css('display', 'block');
                    $(chatWindow).attr('groupname', groupName);
                    $("#chatContainer").append(chatWindow);
                }
                if (listMessages.length < 3) {
                    $('div[groupname=' + groupName + ']').find('ul').append('<li>' + message + '</li>').scrollTop($('html, body').height());
                } else {
                    var toId = $('div[groupname=' + groupName + ']').attr('chattoid')
                    console.log(toId)
                    $('#myModal').find('#ConnectTo').val(toId)
                    $('#myModal').modal()
                }
            };

            $("#broadcast").click(function () {
                // Call the chat method on the server
                chat.server.send($('#msg').val());
            });

            // Start the connection
            $.connection.hub.start(function () {
                chat.server.getAllOnlineStatus();
            });

            $('.UserItem').click(function () {
                    // Pass the Id from the current logged in Member and his chat partner to the Hub method CreateGroup
                    chat.server.createGroup($('#hdnUserId').val(), $(this).attr('data-userid'));
                    var chatWindow = $("#divChatWindow").clone(true);
                    $(chatWindow).attr('chatToId', $(this).attr('data-userid'));
                    $("#chatContainer").append(chatWindow);

                return false;
            });

            // submit button click event
            $(".ChatSend").click(function () {
                strChatText = $('.ChatText', $(this).parent()).val();
                if (strChatText != '') {
                    var strGroupName = $(this).parent().attr('groupname');
                    if (typeof strGroupName !== 'undefined' && strGroupName !== false)
                        chat.server.send($("#hdnUserName").val() + ' : ' + strChatText, $(this).parent().attr('groupname'));
                    $('.ChatText', $(this).parent()).find('ul').append(strChatText);
                    $('.ChatText', $(this).parent()).val('');
                }

                return false;
            });

            $(".ChatText").keypress(function (e) {
                if (e.keyCode == 13) {
                    strChatText = $('.ChatText', $(this).parent()).val();
                    if (strChatText != '') {
                        var strGroupName = $(this).parent().attr('groupname');
                        if (typeof strGroupName !== 'undefined' && strGroupName !== false)
                            chat.server.send($("#hdnUserName").val() + ' : ' + strChatText, $(this).parent().attr('groupname'));
                        $('.ChatText', $(this).parent()).find('ul').append(strChatText);
                        $('.ChatText', $(this).parent()).val('');
                    }
                }
            });

        });

    </script>

1 个答案:

答案 0 :(得分:0)

您需要跟踪用户的状态(该功能不会构建到signalR中),并且只向在线用户发送数据。

请看一下如何跟踪在线用户https://www.simple-talk.com/dotnet/asp.net/tracking-online-users-with-signalr/