我有一个在线聊天室,工作正常。但是,我希望能够向离线用户发送消息。如何修改下面的代码以实现此更改?
我想将ConnectedUsers更改为AllUsers,但是对于离线用户,我没有ConnectionId。
ChatHub.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using catchme.bg.Data;
using catchme.bg.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
namespace catchme.bg
{
[Authorize]
public class ChatHub : Hub
{
private CatchmeContext _context { get; set; }
public ChatHub(CatchmeContext context)
{
_context = context;
}
#region Data Members
static List<UserDetail> ConnectedUsers = new List<UserDetail>();
static List<MessageDetail> CurrentMessage = new List<MessageDetail>();
static List<PrivateMessageDetail> CurrentPrivateMessage = new List<PrivateMessageDetail>();
#endregion
#region Methods
public override async Task OnConnectedAsync()
{
var userName = Context.User.Identity.Name;
var id = Context.ConnectionId;
if (ConnectedUsers.Count(x => x.ConnectionId == id) == 0)
{
ConnectedUsers.Add(new UserDetail {ConnectionId = id, UserName = userName});
CurrentMessage.Clear();
CurrentPrivateMessage.Clear();
foreach (var user_name in ConnectedUsers.Select(u=>u.UserName).Distinct())
{
CurrentMessage.AddRange(GetMessageDetailsForUser(user_name).Result);
CurrentPrivateMessage.AddRange(GetPrivateMessageDetailsForUsers(Context.User.Identity.Name, user_name).Result);
}
// send to caller
await Clients.Caller.SendAsync("OnConnected", id, userName, ConnectedUsers, CurrentMessage, CurrentPrivateMessage);
// send to all except caller client
await Clients.AllExcept(id).SendAsync("NewUserConnected", id, userName, CurrentPrivateMessage);
}
}
public async Task SendMessageToAll(string message)
{
var userName = Context.User.Identity.Name;
// store last 100 messages in cache
AddMessageinCache(userName, message);
// Broad cast message
await Clients.All.SendAsync("MessageReceived", userName, message);
}
public async Task SendPrivateMessage(string toUserId, string message)
{
string fromUserId = Context.ConnectionId;
var toUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == toUserId);
var fromUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == fromUserId);
if (toUser != null && fromUser != null)
{
// send to
await Clients.Client(toUserId).SendAsync("SendPrivateMessage", fromUserId, fromUser.UserName, message);
// send to caller user
await Clients.Caller.SendAsync("SendPrivateMessage", toUserId, fromUser.UserName, message);
AddPrivateMessageinCache(fromUser.UserName, toUser.UserName, message);
}
}
public override async Task OnDisconnectedAsync(Exception ex)
{
var item = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
if (item != null)
{
ConnectedUsers.Remove(item);
var id = Context.ConnectionId;
await Clients.All.SendAsync("UserDisconnected", id, item.UserName);
}
}
#endregion
#region public Messages
private void AddMessageinCache(string userName, string message)
{
var publicMessage = new MessageDetail {UserName = userName, Message = message};
CurrentMessage.Add(publicMessage);
_context.MessageDetails.Add(publicMessage);
_context.SaveChanges();
if (CurrentMessage.Count > 100)
{
CurrentMessage.RemoveAt(0);
_context.MessageDetails.Remove(CurrentMessage[0]);
_context.SaveChanges();
}
}
#endregion
#region private Messages
private void AddPrivateMessageinCache(string userFrom, string userTo, string message)
{
var privateMessage = new PrivateMessageDetail { UserNameFrom = userFrom, UserNameTo = userTo, Message = message };
CurrentPrivateMessage.Add(privateMessage);
_context.PrivateMessageDetails.Add(privateMessage);
_context.SaveChanges();
var singleUserPrivateMessages = CurrentPrivateMessage.Where(u => u.UserNameFrom == userFrom && u.UserNameTo == userTo).ToList();
if (singleUserPrivateMessages.Count > 100)
{
CurrentPrivateMessage.Remove(singleUserPrivateMessages.First());
_context.PrivateMessageDetails.Remove(singleUserPrivateMessages.First());
_context.SaveChanges();
}
}
#endregion
public async Task<List<MessageDetail>> GetMessageDetailsForUser(string userName)
{
return await _context.MessageDetails.Where(u=>u.UserName==userName).ToListAsync();
}
public async Task<List<PrivateMessageDetail>> GetPrivateMessageDetailsForUsers(string userFrom, string userTo)
{
return await _context.PrivateMessageDetails.Where(u => u.UserNameFrom == userFrom && u.UserNameTo== userTo).ToListAsync();
}
}
}
Index.cshtml
@*<div>
<form id="send-form" action="#">
Send a message:
<input type="text" id="message-textbox" disabled/>
<button id="send-button" type="submit" disabled>Send</button>
</form>
<ul id="messages-list"></ul>
</div>
@section Scripts{
<script src="~/lib/signalr/signalr.min.js"></script>
<script src="~/js/chat.js"></script>
}*@
<link href="~/ChatStyle.css" rel="stylesheet" />
<link href="~/lib/jquery-ui/themes/base/jquery-ui.css" rel="stylesheet" />
@section Scripts{
@*<script src="~/lib/jquery-ui/ui/minified/core.js"></script>*@
<script src="~/lib/jquery-ui/jquery-ui.js"></script>
<script src="~/lib/jquery-ui/ui/minified/widget.js"></script>
<script src="~/lib/jquery-ui/ui/widgets/mouse.js"></script>
<script src="~/lib/jquery-ui/ui/widgets/draggable.js"></script>
<script src="~/lib/jquery-ui/ui/widgets/resizable.js"></script>
<script src="~/lib/signalr/signalr.min.js"></script>
<script src="~/js/chatjs.js"></script>
}
<div id="header">
Chat Room
</div>
<br />
<br />
<br />
<div id="divContainer">
@*<div id="divLogin" class="login">
<div>
Your Name:<br />
<input id="txtNickName" type="text" class="textBox" />
</div>
<div id="divButton">
<input id="btnStartChat" type="button" class="submitButton" value="Start Chat" />
</div>
</div>*@
<div id="divChat" class="chatRoom">
<div class="title">
Welcome to Chat Room [<span id='spanUser'></span>]
</div>
<div class="content">
<div id="divChatWindow" class="chatWindow">
</div>
<div id="divusers" class="users">
</div>
</div>
<div class="messageBar">
<input class="textbox" type="text" id="txtMessage" />
<input id="btnSendMsg" type="button" value="Send" class="submitButton" />
</div>
</div>
<input id="hdId" type="hidden" />
<input id="hdUserName" type="hidden" />
</div>
chatjs.js
$(function () {
setScreen(false);
var connection = new signalR.HubConnectionBuilder()
.withUrl("/hubs/chat")
.configureLogging(signalR.LogLevel.Information)
.build();
connection.start().catch(err => console.error(err.toString())).then(function () {
registerClientMethods(connection);
registerEvents(connection);
});
});
function setScreen(isLogin) {
if (!isLogin) {
$("#divChat").hide();
//$("#divLogin").show();
} else {
$("#divChat").show();
//$("#divLogin").hide();
}
}
function AddUser(connection, id, name, privateMessages) {
var userId = $('#hdId').val();
var code = "";
if (userId == id) {
code = $('<div class="loginUser">' + name + "</div>");
} else {
code = $('<a id="' + id + '" class="user" >' + name + '<a>');
$(code).dblclick(function () {
var id = $(this).attr('id');
if (userId != id)
OpenPrivateChatWindow(connection, id, name, privateMessages);
});
}
$("#divusers").append(code);
}
function AddMessage(userName, message) {
$('#divChatWindow').append('<div class="message"><span class="userName">' +
userName +
'</span>: ' +
message +
'</div>');
var height = $('#divChatWindow')[0].scrollHeight;
$('#divChatWindow').scrollTop(height);
}
function registerEvents(connection) {
$("#btnStartChat").click(function () {
var name = $("#txtNickName").val();
if (name.length > 0) {
connection.server.connect(name);
} else {
alert("Please enter name");
}
});
$('#btnSendMsg').click(function () {
var msg = $("#txtMessage").val();
if (msg.length > 0) {
//var userName = $('#hdUserName').val();
connection.send("SendMessageToAll", msg);
$("#txtMessage").val('');
}
});
$("#txtNickName").keypress(function (e) {
if (e.which == 13) {
$("#btnStartChat").click();
}
});
$("#txtMessage").keypress(function (e) {
if (e.which == 13) {
$('#btnSendMsg').click();
}
});
}
function registerClientMethods(connection) {
// Calls when user successfully logged in
connection.on("OnConnected",
function (id, userName, allUsers, messages, privateMessages) {
setScreen(true);
$('#hdId').val(id);
$('#hdUserName').val(userName);
$('#spanUser').html(userName);
// Add All Users
for (i = 0; i < allUsers.length; i++) {
AddUser(connection, allUsers[i].connectionId, allUsers[i].userName, privateMessages);
}
// Add Existing Public Messages
for (i = 0; i < messages.length; i++) {
AddMessage(messages[i].userName, messages[i].message);
}
// Add Existing Private Messages
for (i = 0; i < privateMessages.length; i++) {
AddMessage(privateMessages[i].userName, messages[i].message);
}
});
// On New User Connected
connection.on("NewUserConnected",
function (id, name, privateMesssages) {
AddUser(connection, id, name, privateMesssages);
});
// On User Disconnected
connection.on("UserDisconnected",
function (id, userName) {
$('#' + id).remove();
var ctrId = 'private_' + id;
$('#' + ctrId).remove();
var disc = $('<div class="disconnect">"' + userName + '" logged off.</div>');
$(disc).hide();
$('#divusers').prepend(disc);
$(disc).fadeIn(200).delay(2000).fadeOut(200);
});
connection.on("MessageReceived",
function (userName, message) {
AddMessage(userName, message);
});
connection.on("SendPrivateMessage",
function (windowId, fromUserName, message) {
var ctrId = 'private_' + windowId;
if ($('#' + ctrId).length == 0) {
createPrivateChatWindow(connection, windowId, ctrId, fromUserName);
}
$('#' + ctrId).find('#divMessage').append('<div class="message"><span class="userName">' +
fromUserName +
'</span>: ' +
message +
'</div>');
// set scrollbar
var height = $('#' + ctrId).find('#divMessage')[0].scrollHeight;
$('#' + ctrId).find('#divMessage').scrollTop(height);
});
}
function OpenPrivateChatWindow(connection, id, userName, privateMessages) {
var ctrId = 'private_' + id;
if ($('#' + ctrId).length > 0) return;
createPrivateChatWindow(connection, id, ctrId, userName);
//Add Private Messages
for (i = 0; i < privateMessages.length; i++) {
$('#' + ctrId).find('#divMessage').append('<div class="message"><span class="userName">' +
privateMessages[i].userNameFrom +
'</span>: ' +
privateMessages[i].message +
'</div>');
}
// set scrollbar
var height = $('#' + ctrId).find('#divMessage')[0].scrollHeight;
$('#' + ctrId).find('#divMessage').scrollTop(height);
}
function createPrivateChatWindow(connection, userId, ctrId, userName) {
var div = '<div id="' +
ctrId +
'" class="ui-widget-content draggable" rel="0">' +
'<div class="header">' +
'<div style="float:right;">' +
'<img id="imgDelete" style="cursor:pointer;" src="/images/delete.png"/>' +
'</div>' +
'<span class="selText" rel="0">' +
userName +
'</span>' +
'</div>' +
'<div id="divMessage" class="messageArea">' +
'</div>' +
'<div class="buttonBar">' +
'<input id="txtPrivateMessage" class="msgText" type="text" />' +
'<input id="btnSendMessage" class="submitButton button" type="button" value="Send" />' +
'</div>' +
'</div>';
var $div = $(div);
// DELETE BUTTON IMAGE
$div.find('#imgDelete').click(function () {
$('#' + ctrId).remove();
});
// Send Button event
$div.find("#btnSendMessage").click(function () {
$textBox = $div.find("#txtPrivateMessage");
var msg = $textBox.val();
if (msg.length > 0) {
connection.send("SendPrivateMessage", userId, msg);
$textBox.val('');
}
});
// Text Box event
$div.find("#txtPrivateMessage").keypress(function (e) {
if (e.which === 13) {
$div.find("#btnSendMessage").click();
}
});
AddDivToContainer($div);
}
function AddDivToContainer($div) {
$('#divContainer').prepend($div);
$div.draggable({
handle: ".header",
stop: function () {
}
});
////$div.resizable({
//// stop: function () {
//// }
////});
}
答案 0 :(得分:4)
请遵循以下步骤。
希望您会理解,您需要在技术上实施它。