asp.net-mvc – 朋友列表与chatjs.net SignalR MVC聊天
发布时间:2020-12-16 03:23:07 所属栏目:asp.Net 来源:网络整理
导读:我开始使用 chatjs.net实现网络聊天系统.但我不知道朋友列表应该绑定聊天列表.我推荐房间聊天与ROOM_ID_STUB是用户名记录.但我的案例中的朋友列表将显示在线和离线用户,不像所有示例chatjs.net只会是单人间. 任何人都可以建议我绑定我的朋友列表的正确方法,
我开始使用
chatjs.net实现网络聊天系统.但我不知道朋友列表应该绑定聊天列表.我推荐房间聊天与ROOM_ID_STUB是用户名记录.但我的案例中的朋友列表将显示在线和离线用户,不像所有示例chatjs.net只会是单人间.
任何人都可以建议我绑定我的朋友列表的正确方法,并记录每个用户将有一个聊天室,他们一起分享房间聊天列表? 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,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(); } } 解决方法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); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- 从asp.net中的gridview获取已检查的行
- asp.net-web-api – 带协议缓冲区的ASP.NET WebApi – 错误
- ASP.NET清空缓存时遇到的问题简析
- Asp.net静态可变生命周期刷新和PostBack
- asp.net-mvc – 遵循视图模型模式的最佳实践
- asp.net – 如何使用Response.OutputStream.Write将文件发送
- ASP.NET WebHooks和Signal-R之间的区别
- asp.net-mvc-3 – 通过使用jQuery Script调用URL.Action生成
- 从ViewBag设置文本输入的值? ASP.NET MVC5
- asp.net-mvc-3 – 具有ASP.NET MVC3和嵌入式Razor视图的插件