Asp.net mvc 与chatjs.net Signaler MVC的好友列表聊天
我开始使用实现一个web聊天系统。但是我想知道朋友列表应该绑定聊天列表。我指的是带有room_ID_存根的聊天室已记录用户名。但在我的例子中,朋友列表将显示在线和离线用户,与所有示例不同,chatjs.net将只显示单人房间 有人能给我建议绑定好友列表的正确方法吗?每个登录的用户都有一个聊天室,他们一起共享聊天室列表Asp.net mvc 与chatjs.net Signaler MVC的好友列表聊天,asp.net-mvc,chat,signalr,chatjs,Asp.net Mvc,Chat,Signalr,Chatjs,我开始使用实现一个web聊天系统。但是我想知道朋友列表应该绑定聊天列表。我指的是带有room_ID_存根的聊天室已记录用户名。但在我的例子中,朋友列表将显示在线和离线用户,与所有示例不同,chatjs.net将只显示单人房间 有人能给我建议绑定好友列表的正确方法吗?每个登录的用户都有一个聊天室,他们一起共享聊天室列表 public class ChatHub : Hub, IChatHub { /// <summary> /// This ST
public class ChatHub : Hub, IChatHub
{
/// <summary>
/// This STUB. In a normal situation, there would be multiple rooms and the user room would have to be
/// determined by the user profile
/// </summary>
public const string ROOM_ID_STUB = "chatjs-room";
/// <summary>
/// Current connections
/// 1 room has many users that have many connections (2 open browsers from the same user represents 2 connections)
/// </summary>
private static readonly Dictionary<string, Dictionary<int, List<string>>> connections = new Dictionary<string, Dictionary<int, List<string>>>();
/// <summary>
/// This is STUB. This will SIMULATE a database of chat messages
/// </summary>
private static readonly List<DbChatMessageStub> dbChatMessagesStub = new List<DbChatMessageStub>();
/// <summary>
/// This method is STUB. This will SIMULATE a database of users
/// </summary>
private static readonly List<DbUserStub> dbUsersStub = new List<DbUserStub>();
/// <summary>
/// This method is STUB. In a normal situation, the user info would come from the database so this method wouldn't be necessary.
/// It's only necessary because this class is simulating the database
/// </summary>
/// <param name="newUser"></param>
public static void RegisterNewUser(DbUserStub newUser)
{
if (newUser == null) throw new ArgumentNullException("newUser");
dbUsersStub.Add(newUser);
}
/// <summary>
/// This method is STUB. Returns if a user is registered in the FAKE DB.
/// Normally this wouldn't be necessary.
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public static bool IsUserRegisteredInDbUsersStub(DbUserStub user)
{
return dbUsersStub.Any(u => u.Id == user.Id);
}
/// <summary>
/// Tries to find a user with the provided e-mail
/// </summary>
/// <param name="email"></param>
/// <returns></returns>
public static DbUserStub FindUserByEmail(string email)
{
if (email == null) return null;
return dbUsersStub.FirstOrDefault(u => u.Email == email);
}
/// <summary>
/// If the specified user is connected, return information about the user
/// </summary>
public ChatUser GetUserInfo(int userId)
{
var user = dbUsersStub.FirstOrDefault(u => u.Id == userId);
return user == null ? null : GetChatUserFromDbUserId(userId);
}
private ChatUser GetChatUserFromDbUserId(int dbUserId)
{
var myRoomId = this.GetMyRoomId();
// this is STUB. Normally you would go to the database get the real user
var dbUser = dbUsersStub.First(u => u.Id == dbUserId);
ChatUser.StatusType userStatus;
lock (connections)
{
userStatus = connections.ContainsKey(myRoomId)
? (connections[myRoomId].ContainsKey(dbUser.Id)
? ChatUser.StatusType.Online
: ChatUser.StatusType.Offline)
: ChatUser.StatusType.Offline;
}
return new ChatUser()
{
Id = dbUser.Id,
Name = dbUser.FullName,
Status = userStatus,
ProfilePictureUrl = GravatarHelper.GetGravatarUrl(GravatarHelper.GetGravatarHash(dbUser.Email), GravatarHelper.Size.s32)
};
}
private ChatMessage GetChatMessage(DbChatMessageStub chatMessage, string clientGuid)
{
return new ChatMessage()
{
Message = chatMessage.Message,
UserFrom = this.GetChatUserFromDbUserId(chatMessage.UserFromId),
UserTo = this.GetChatUserFromDbUserId(chatMessage.UserToId),
ClientGuid = clientGuid
};
}
/// <summary>
/// Returns my user id
/// </summary>
/// <returns></returns>
private int GetMyUserId()
{
// This would normally be done like this:
//var userPrincipal = this.Context.User as AuthenticatedPrincipal;
//if (userPrincipal == null)
// throw new NotAuthorizedException();
//var userData = userPrincipal.Profile;
//return userData.Id;
// But for this example, it will get my user from the cookie
return ChatCookieHelperStub.GetDbUserFromCookie(this.Context.Request).Id;
}
private string GetMyRoomId()
{
// This would normally be done like this:
//var userPrincipal = this.Context.User as AuthenticatedPrincipal;
//if (userPrincipal == null)
// throw new NotAuthorizedException();
//var userData = userPrincipal.Profile;
//return userData.MyTenancyIdentifier;
// But for this example, it will always return "chatjs-room", because we have only one room.
return ROOM_ID_STUB;
}
/// <summary>
/// Broadcasts to all users in the same room the new users list
/// </summary>
private void BroadcastUsersList()
{
var myRoomId = this.GetMyRoomId();
var connectionIds = new List<string>();
lock (connections)
{
if (connections.ContainsKey(myRoomId))
connectionIds = connections[myRoomId].Keys.SelectMany(userId => connections[myRoomId][userId]).ToList();
}
// gets the current room user's list
// this is STUB. You would normally go to the database to get the real room users
var dbRoomUsers = dbUsersStub.Where(u => u.TenancyId == myRoomId).OrderBy(u => u.FullName).ToList();
var usersList = dbRoomUsers.Select(u => this.GetChatUserFromDbUserId(u.Id)).ToList();
foreach (var connectionId in connectionIds)
this.Clients.Client(connectionId).usersListChanged(usersList);
}
private DbChatMessageStub PersistMessage(int otherUserId, string message)
{
var myUserId = this.GetMyUserId();
// this is STUB. Normally you would go to the real database to get the my user and the other user
var myUser = dbUsersStub.FirstOrDefault(u => u.Id == myUserId);
var otherUser = dbUsersStub.FirstOrDefault(u => u.Id == otherUserId);
if (myUser == null || otherUser == null)
return null;
var dbChatMessage = new DbChatMessageStub()
{
Date = DateTime.UtcNow,
Message = message,
UserFromId = myUserId,
UserToId = otherUserId,
TenancyId = myUser.TenancyId
};
// this is STUB. Normally you would add the dbMessage to the real database
dbChatMessagesStub.Add(dbChatMessage);
// normally you would save the database changes
//this.db.SaveChanges();
return dbChatMessage;
}
/// <summary>
/// Returns the message history
/// </summary>
public List<ChatMessage> GetMessageHistory(int otherUserId)
{
var myUserId = this.GetMyUserId();
// this is STUB. Normally you would go to the real database to get the messages
var dbMessages = dbChatMessagesStub
.Where(
m =>
(m.UserToId == myUserId && m.UserFromId == otherUserId) ||
(m.UserToId == otherUserId && m.UserFromId == myUserId))
.OrderByDescending(m => m.Date).Take(30).ToList();
dbMessages.Reverse();
return dbMessages.Select(m => this.GetChatMessage(m, null)).ToList();
}
/// <summary>
/// Sends a message to a particular user
/// </summary>
public void SendMessage(int otherUserId, string message, string clientGuid)
{
var myUserId = this.GetMyUserId();
var myRoomId = this.GetMyRoomId();
var dbChatMessage = PersistMessage(otherUserId, message);
var connectionIds = new List<string>();
lock (connections)
{
if (connections[myRoomId].ContainsKey(otherUserId))
connectionIds.AddRange(connections[myRoomId][otherUserId]);
if (connections[myRoomId].ContainsKey(myUserId))
connectionIds.AddRange(connections[myRoomId][myUserId]);
}
foreach (var connectionId in connectionIds)
this.Clients.Client(connectionId).sendMessage(this.GetChatMessage(dbChatMessage, clientGuid));
}
/// <summary>
/// Sends a typing signal to a particular user
/// </summary>
public void SendTypingSignal(int otherUserId)
{
var myUserId = this.GetMyUserId();
var myRoomId = this.GetMyRoomId();
var connectionIds = new List<string>();
lock (connections)
{
if (connections[myRoomId].ContainsKey(otherUserId))
connectionIds.AddRange(connections[myRoomId][otherUserId]);
}
foreach (var connectionId in connectionIds)
this.Clients.Client(connectionId).sendTypingSignal(this.GetUserInfo(myUserId));
}
public override Task OnConnected()
{
var myRoomId = this.GetMyRoomId();
var myUserId = this.GetMyUserId();
lock (connections)
{
if (!connections.ContainsKey(myRoomId))
connections[myRoomId] = new Dictionary<int, List<string>>();
if (!connections[myRoomId].ContainsKey(myUserId))
connections[myRoomId][myUserId] = new List<string>();
connections[myRoomId][myUserId].Add(this.Context.ConnectionId);
}
this.BroadcastUsersList();
return base.OnConnected();
}
public override Task OnDisconnected()
{
var myRoomId = this.GetMyRoomId();
var myUserId = this.GetMyUserId();
lock (connections)
{
if (connections.ContainsKey(myRoomId))
if (connections[myRoomId].ContainsKey(myUserId))
if (connections[myRoomId][myUserId].Contains(this.Context.ConnectionId))
{
connections[myRoomId][myUserId].Remove(this.Context.ConnectionId);
if (!connections[myRoomId][myUserId].Any())
{
connections[myRoomId].Remove(myUserId);
Task.Factory.StartNew(() =>
{
// this will run in separate thread.
// If the user is away for more than 10 seconds it will be removed from
// the room.
// In a normal situation this wouldn't be done because normally the users in a
// chat room are fixed, like when you have 1 chat room for each tenancy
Thread.Sleep(10000);
if (!connections[myRoomId].ContainsKey(myUserId))
{
var myDbUser = dbUsersStub.FirstOrDefault(u => u.Id == myUserId);
if (myDbUser != null)
{
dbUsersStub.Remove(myDbUser);
this.BroadcastUsersList();
}
}
});
}
}
}
return base.OnDisconnected();
}
}
公共类聊天中心:集线器,iCathub
{
///
///此存根。在正常情况下,将有多个房间,用户房间必须是
///由用户配置文件确定
///
公共建筑字符串室\u ID\u STUB=“聊天室”;
///
///电流连接
///1个文件室有多个具有多个连接的用户(来自同一用户的2个打开的浏览器表示2个连接)
///
私有静态只读字典连接=新建字典();
///
///这是存根。这将模拟聊天消息的数据库
///
私有静态只读列表dbChatMessagesStub=新列表();
///
///此方法是存根。这将模拟用户数据库
///
私有静态只读列表dbUsersStub=new List();
///
///此方法是存根。在正常情况下,用户信息将来自数据库,因此不需要此方法。
///这只是因为这个类正在模拟数据库
///
///
公共静态无效寄存器newUser(DbUserStub newUser)
{
如果(newUser==null)抛出新ArgumentNullException(“newUser”);
添加(newUser);
}
///
///此方法为存根。如果用户在假数据库中注册,则返回。
///通常这是不必要的。
///
///
///
公共静态bool IsUserRegisteredInDbUsersStub(DbUserStub用户)
{
返回dbUsersStub.Any(u=>u.Id==user.Id);
}
///
///尝试使用提供的电子邮件查找用户
///
///
///
公共静态DbUserStub FindUserByMail(字符串电子邮件)
{
如果(email==null)返回null;
返回dbUsersStub.FirstOrDefault(u=>u.Email==Email);
}
///
///如果指定的用户已连接,则返回有关该用户的信息
///
公共聊天用户GetUserInfo(int userId)
{
var user=dbUsersStub.FirstOrDefault(u=>u.Id==userId);
返回user==null?null:GetChatUserFromDbUserId(userId);
}
私有聊天用户GetChatUserFromDbUserId(int-dbUserId)
{
var myRoomId=this.GetMyRoomId();
//这是存根。通常你会去数据库找到真正的用户
var dbUser=dbUsersStub.First(u=>u.Id==dbUserId);
ChatUser.StatusType用户状态;
锁(连接)
{
userStatus=connections.ContainsKey(myRoomId)
?(连接[myRoomId].ContainsKey(dbUser.Id)
?ChatUser.StatusType.Online
:ChatUser.StatusType.Offline)
:ChatUser.StatusType.Offline;
}
返回新的聊天用户()
{
Id=dbUser.Id,
Name=dbUser.FullName,
Status=userStatus,
ProfilePictureUrl=gravatalPer.GetGravatarUrl(gravatalPer.GetGravatarHash(dbUser.Email),gravatalPer.Size.s32)
};
}
私有ChatMessage GetChatMessage(dbchatmessage存根ChatMessage,字符串clientGuid)
{
返回新的聊天室消息()
{
Message=chatMessage.Message,
UserFrom=this.GetChatUserFromDbUserId(chatMessage.UserFromId),
UserTo=this.GetChatUserFromDbUserId(chatMessage.UserToId),
ClientGuid=ClientGuid
};
}
///
///返回我的用户id
///
///
私有int GetMyUserId()
{
//这通常是这样做的:
//var userPrincipal=this.Context.User作为AuthenticatedPrincipal;
//if(userPrincipal==null)
//抛出新的NotAuthorizedException();
//var userData=userPrincipal.Profile;
//返回userData.Id;
//但是对于这个例子,它将从cookie中获取我的用户
返回ChatCookieHelperStub.GetDbUserFromCookie(this.Context.Request).Id;
}
私有字符串GetMyRoomId()
{
//这通常是这样做的:
//var userPrincipal=this.Context.User作为AuthenticatedPrincipal;
//if(userPrincipal==null)
//抛出新的NotAuthorizedException();
//var userData=userPrincipal.Profile;
//返回userData.mytenacyIdentifier;
//但是对于这个例子,它总是返回“chatjs-room”,因为我们只有一个房间。
返回房间的ID存根;
}
///
///向同一房间中的所有用户广播新用户列表
///
私有void BroadcastUsersList()
{
var myRoomId=this.GetMyRoomId();
var connectionId=新列表();
锁(连接)
{
if(connections.ContainsKey(myRoomId))
ConnectionId=connections[myRoomId].Keys.SelectMany(userId=>connections[myRoomId][userId]).ToList();
}
//获取当前文件室用户的列表
//这是存根。你通常会去数据库找到真正的房间用户
private void BroadcastUsersList()
{
var myRoomId = this.GetMyRoomId();
var connectionIds = new List<string>();
lock (connections)
{
if (connections.ContainsKey(myRoomId))
connectionIds = connections[myRoomId].Keys.SelectMany(userId => connections[myRoomId][userId]).ToList();
}
List<UserSite> dbRoomUsers = new List<UserSite>();
int myId = GetMyUserId();
List<Int>listFriendId = getListUserIdFriendOfUser(myId);
listFriendId.Add(myId);
foreach (var item in dbUsersStub)
{
if (listFriendId.Contains(item.Id))
dbRoomUsers.Add(item);
}
var usersList = dbRoomUsers.Select(u => this.GetChatUserFromDbUserId(u.Id)).ToList();
foreach (var connectionId in connectionIds)
this.Clients.Client(connectionId).usersListChanged(usersList);
}