• Asp.NET MVC 使用 SignalR 实现推送功能二(Hubs 在线聊天室 获取保存用户信息)


    简单介绍

    关于SignalR的简单实用 请参考 Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室)

    在上一篇中,我们只是介绍了简单的消息推送,今天我们来修改一下,实现保存消息,历史消息和用户在线

    由于,我这是在一个项目(【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目 目录索引)的基础上做的,所以使用到的一些借口和数据表,不详细解析,只是介绍一下思路和实现方式,供大家参考

    用户登录注册信息

    当用户登录之后,我们注册一下用户的信息,我们在ChatHub中 新建一个方法 Register(用户帐号,用户密码)

    前台js调用这个方法实现用户注册 

    1 $.connection.hub.start().done(function () {            
    2             chat.server.register('用户帐号', '用户密码');           
    3         });

     Register方法的实现:

     1 /// <summary>
     2         /// 用户登录注册信息
     3         /// </summary>
     4         /// <param name="id"></param>
     5         public void Register(string account,string password)
     6         {
     7             try
     8             {
     9                 //获取用户信息
    10                 var User = UserManage.Get(p => p.ACCOUNT == account);
    11                 if (User != null && User.PASSWORD == password)
    12                 {
    13                     //更新在线状态
    14                     var UserOnline = UserOnlineManage.LoadListAll(p => p.FK_UserId == User.ID).FirstOrDefault();
    15                     UserOnline.ConnectId = Context.ConnectionId;
    16                     UserOnline.OnlineDate = DateTime.Now;
    17                     UserOnline.IsOnline = true;
    18                     UserOnline.UserIP = Utils.GetIP();
    19                     UserOnlineManage.Update(UserOnline);
    20                     
    21 
    22                     //超级管理员
    23                     if (User.ID == ClsDic.DicRole["超级管理员"])
    24                     {
    25                         //通知用户上线
    26                         Clients.All.UserLoginNotice("超级管理员:" + User.NAME + " 上线了!");
    27 
    28                     }
    29                     else
    30                     {
    31                         //获取用户一级部门信息
    32                         var Depart = GetUserDepart(User.DPTID);
    33                         if (Depart != null && !string.IsNullOrEmpty(Depart.ID))
    34                         {
    35                             //添加用户到部门群组 Groups.Add(用户连接ID,群组)
    36                             Groups.Add(Context.ConnectionId, Depart.ID);
    37                             //通知用户上线
    38                             Clients.All.UserLoginNotice(Depart.NAME + " - " + CodeManage.Get(m => m.CODEVALUE == User.LEVELS && m.CODETYPE == "ZW").NAMETEXT + "" + User.NAME + " 上线了!");
    39                             
    40 
    41                         }
    42                     }
    43                     //刷新用户通讯录
    44                     Clients.All.ContactsNotice(JsonConverter.Serialize(UserOnline));                    
    45                 }
    46             }
    47             catch(Exception ex)
    48             {
    49                 Clients.Client(Context.ConnectionId).UserLoginNotice("出错了:" + ex.Message);
    50                 throw ex.InnerException;
    51             }
    52             
    53         }

     用户上线通知,大家可以在对话框内已系统消息的方式提示,我这里是一个toastr插件的提示

    1 //用户上线通知
    2         chat.client.UserLoginNotice = function (message) {
    3             if ($("#LoginNotice").prop("checked")) { toasSuccess.message_t(message); }
    4         };

    这里面有个判断,如果用户允许提醒,就提示,如果不允许,就不提示,就是个checkbox

    当用户登录后,刷新其它用户通讯录用户的在线状态,离线用户排到底部,并且如果用户离线,点击用户的时候,提示用户离线发送邮件还是离线消息

     1 //通讯录用户上下线
     2         chat.client.ContactsNotice = function (message) {
     3             var data = eval("(" + message + ")");
     4             if (!data.IsOnline) {
     5                 var current = $("#charUser-" + data.FK_UserId).addClass("offline");
     6                 var parentId = current.parent().parent().prop("id");
     7                 current.remove().appendTo($("#" + parentId + " .panel-body"));
     8             }else
     9             {
    10                 var current = $("#charUser-" + data.FK_UserId).removeClass("offline").attr("data-connectid", data.ConnectId);
    11                 var parentId = current.parent().parent().prop("id");
    12                 current.insertBefore($("#" + parentId + " .panel-body .offline").eq(0));
    13             }
    14             $(".panel-body .chat-user").click(function () {
    15                 if ($(this).hasClass("offline")) {
    16                     var MailId = $(this).attr("data-Email");
    17                     var ConnectId = $(this).attr("data-connectid");
    18                     var UserName = $(this).attr("data-username");
    19                     swal({ title: "用户离线", text: "当前用户不在线,是否发送邮件?", type: "warning", showCancelButton: true, confirmButtonColor: "#DD6B55", confirmButtonText: "发送邮件", cancelButtonText: "发送离线消息", closeOnConfirm: false, closeOnCancel: false }, function (isConfirm) { if (isConfirm) { sweetAlert.close(); document.getElementById(MailId).click(); } else { sweetAlert.close(); ChatPerson(ConnectId, UserName); } });
    20                 }
    21                 else {
    22                     ChatPerson($(this).attr("data-connectid"), $(this).attr("data-username"));
    23                 }
    24             });
    25 
    26         };

    在线:

    离线:

    用户离线

    我们重写OnDisconnected方法,当用户离线时,更新用户状态 同时刷新其它用户通讯录用户在线状态

     1  //使用者离线
     2         public override Task OnDisconnected(bool stopCalled)
     3         {
     4             //更新在线状态
     5             var UserOnline = UserOnlineManage.LoadListAll(p => p.ConnectId == Context.ConnectionId).FirstOrDefault();
     6             UserOnline.ConnectId = Context.ConnectionId;
     7             UserOnline.OfflineDate = DateTime.Now;
     8             UserOnline.IsOnline = false;
     9             UserOnlineManage.Update(UserOnline);
    10 
    11             //获取用户信息
    12             var User = UserManage.Get(p => p.ID == UserOnline.FK_UserId);
    13 
    14             Clients.All.UserLogOutNotice(User.NAME + ":离线了!");
    15             //刷新用户通讯录
    16             Clients.All.ContactsNotice(JsonConverter.Serialize(UserOnline));
    17 
    18             return base.OnDisconnected(true);
    19         }

    前台离线通知

    1  //用户离线通知
    2         chat.client.UserLogOutNotice = function (message) {
    3             if ($("#LogOutNotice").prop("checked")) { toasInfo.message_t(message); }
    4         };

    获取历史消息

    我是在用户登录的时候获取用户消息的,大家可以放到其它逻辑中

    Register方法添加用户历史消息

     1 /// <summary>
     2         /// 用户登录注册信息
     3         /// </summary>
     4         /// <param name="id"></param>
     5         public void Register(string account,string password)
     6         {
     7             try
     8             {
     9                 //获取用户信息
    10                 var User = UserManage.Get(p => p.ACCOUNT == account);
    11                 if (User != null && User.PASSWORD == password)
    12                 {
    13                     //更新在线状态
    14                     var UserOnline = UserOnlineManage.LoadListAll(p => p.FK_UserId == User.ID).FirstOrDefault();
    15                     UserOnline.ConnectId = Context.ConnectionId;
    16                     UserOnline.OnlineDate = DateTime.Now;
    17                     UserOnline.IsOnline = true;
    18                     UserOnline.UserIP = Utils.GetIP();
    19                     UserOnlineManage.Update(UserOnline);
    20 
    21                     //获取历史消息
    22                     int days = Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["HistoryDays"]);
    23                     DateTime dtHistory = DateTime.Now.AddDays(-days);
    24                     var ChatMessageList = ChatMessageManage.LoadAll(p => p.MessageDate > dtHistory);                    
    25 
    26                     //超级管理员
    27                     if (User.ID == ClsDic.DicRole["超级管理员"])
    28                     {
    29                         //通知用户上线
    30                         Clients.All.UserLoginNotice("超级管理员:" + User.NAME + " 上线了!");
    31 
    32                         var HistoryMessage = ChatMessageList.OrderBy(p=>p.MessageDate).ToList().Select(p => new
    33                         {
    34                             UserName = UserManage.Get(m => m.ID == p.FromUser).NAME,
    35                             UserFace = string.IsNullOrEmpty(UserManage.Get(m => m.ID == p.FromUser).FACE_IMG) ? "/Pro/Project/User_Default_Avatat?name=" + UserManage.Get(m => m.ID == p.FromUser).NAME.Substring(0, 1) : UserManage.Get(m => m.ID == p.FromUser).FACE_IMG,
    36                             MessageType=GetMessageType(p.MessageType),
    37                             p.FromUser,
    38                             p.MessageContent,
    39                             MessageDate = p.MessageDate.GetDateTimeFormats('D')[1].ToString() + " - " + p.MessageDate.ToString("HH:mm:ss"),
    40                             ConnectId = UserOnlineManage.LoadListAll(m => m.SYS_USER.ID == p.FromUser).FirstOrDefault().ConnectId
    41                         }).ToList();
    42 
    43                         //推送历史消息
    44                         Clients.Client(Context.ConnectionId).addHistoryMessageToPage(JsonConverter.Serialize(HistoryMessage));
    45                     }
    46                     else
    47                     {
    48                         //获取用户一级部门信息
    49                         var Depart = GetUserDepart(User.DPTID);
    50                         if (Depart != null && !string.IsNullOrEmpty(Depart.ID))
    51                         {
    52                             //添加用户到部门群组 Groups.Add(用户连接ID,群组)
    53                             Groups.Add(Context.ConnectionId, Depart.ID);
    54                             //通知用户上线
    55                             Clients.All.UserLoginNotice(Depart.NAME + " - " + CodeManage.Get(m => m.CODEVALUE == User.LEVELS && m.CODETYPE == "ZW").NAMETEXT + "" + User.NAME + " 上线了!");
    56                             //用户历史消息
    57                             int typeOfpublic = Common.Enums.ClsDic.DicMessageType["广播"];
    58                             int typeOfgroup = Common.Enums.ClsDic.DicMessageType["群组"];
    59                             int typeOfprivate = Common.Enums.ClsDic.DicMessageType["私聊"];
    60                             var HistoryMessage = ChatMessageList.Where(p => p.MessageType == typeOfpublic || (p.MessageType == typeOfgroup && p.ToGroup == Depart.ID) || (p.MessageType == typeOfprivate && p.ToGroup == User.ID.ToString())).OrderBy(p => p.MessageDate).ToList().Select(p => new
    61                             {
    62                                 UserName = UserManage.Get(m => m.ID == p.FromUser).NAME,
    63                                 UserFace = string.IsNullOrEmpty(UserManage.Get(m => m.ID == p.FromUser).FACE_IMG) ? "/Pro/Project/User_Default_Avatat?name=" + UserManage.Get(m => m.ID == p.FromUser).NAME.Substring(0, 1) : UserManage.Get(m => m.ID == p.FromUser).FACE_IMG,
    64                                 MessageType = GetMessageType(p.MessageType),
    65                                 p.FromUser,
    66                                 p.MessageContent,
    67                                 MessageDate = p.MessageDate.GetDateTimeFormats('D')[1].ToString() + " - " + p.MessageDate.ToString("HH:mm:ss"),
    68                                 ConnectId = UserOnlineManage.LoadListAll(m => m.SYS_USER.ID == p.FromUser).FirstOrDefault().ConnectId
    69                             }).ToList();
    70                            
    71                             //推送历史消息
    72                             Clients.Client(Context.ConnectionId).addHistoryMessageToPage(JsonConverter.Serialize(HistoryMessage));
    73 
    74                         }
    75                     }
    76                     //刷新用户通讯录
    77                     Clients.All.ContactsNotice(JsonConverter.Serialize(UserOnline));                    
    78                 }
    79             }
    80             catch(Exception ex)
    81             {
    82                 Clients.Client(Context.ConnectionId).UserLoginNotice("出错了:" + ex.Message);
    83                 throw ex.InnerException;
    84             }
    85             
    86         }

    前台:

     1 //接收历史信息
     2         chat.client.addHistoryMessageToPage = function (message) {
     3             var data = eval("(" + message + ")");
     4             var html = '';
     5             for(var i=0;i<data.length;i++)
     6             {
     7                //处理消息
     8             }                        
     9             $(html).appendTo(".chat-discussion");
    10             $('<div class=" col-xs-12 m-t-sm m-b-sm text-center sysmessage"> — 以上是历史消息 — </div>').appendTo(".chat-discussion");                        
    11         };

    发送广播、组播消息

     1 /// <summary>
     2         /// 发送消息(广播、组播)
     3         /// </summary>
     4         /// <param name="message">发送的消息</param>
     5         /// <param name="message">发送的群组</param>
     6         public void Send(string message,string groupId)
     7         {
     8             try 
     9             {
    10                 //消息用户主体
    11                 var UserOnline = UserOnlineManage.LoadListAll(p => p.ConnectId == Context.ConnectionId).FirstOrDefault();
    12                 
    13                 //广播
    14                 if(string.IsNullOrEmpty(groupId))
    15                 {
    16                     //保存消息
    17                     ChatMessageManage.Save(new Domain.SYS_CHATMESSAGE() { FromUser = UserOnline.FK_UserId, MessageType = Common.Enums.ClsDic.DicMessageType["广播"], MessageContent = message, MessageDate = DateTime.Now, MessageIP = Utils.GetIP() });
    18                     //返回消息实体
    19                     var Message = new Message() { ConnectId = UserOnline.ConnectId, UserName = UserOnline.SYS_USER.NAME, UserFace = string.IsNullOrEmpty(UserOnline.SYS_USER.FACE_IMG) ? "/Pro/Project/User_Default_Avatat?name=" + UserOnline.SYS_USER.NAME.Substring(0, 1) : UserOnline.SYS_USER.FACE_IMG, MessageDate = DateTime.Now.GetDateTimeFormats('D')[1].ToString() + " - " + DateTime.Now.ToString("HH:mm:ss"), MessageContent = message, MessageType = "public", UserId = UserOnline.SYS_USER.ID };
    20 
    21                     //推送消息
    22                     Clients.All.addNewMessageToPage(JsonConverter.Serialize(Message));
    23                 }
    24                 //组播
    25                 else
    26                 {
    27                     //保存消息
    28                     ChatMessageManage.Save(new Domain.SYS_CHATMESSAGE() { FromUser = UserOnline.FK_UserId, MessageType = Common.Enums.ClsDic.DicMessageType["群组"], MessageContent = message, MessageDate = DateTime.Now, MessageIP = Utils.GetIP(), ToGroup = groupId });
    29                     //返回消息实体
    30                     var Message = new Message() { ConnectId = UserOnline.ConnectId, UserName = UserOnline.SYS_USER.NAME, UserFace = string.IsNullOrEmpty(UserOnline.SYS_USER.FACE_IMG) ? "/Pro/Project/User_Default_Avatat?name=" + UserOnline.SYS_USER.NAME.Substring(0, 1) : UserOnline.SYS_USER.FACE_IMG, MessageDate = DateTime.Now.GetDateTimeFormats('D')[1].ToString() + " - " + DateTime.Now.ToString("HH:mm:ss"), MessageContent = message, MessageType = "group", UserId = UserOnline.SYS_USER.ID };
    31 
    32                     //推送消息
    33                     Clients.Group(groupId).addNewMessageToPage(JsonConverter.Serialize(Message));
    34                     //如果用户不在群组中则单独推送消息给用户
    35                     var Depart = GetUserDepart(UserOnline.SYS_USER.DPTID);
    36                     if(Depart==null)
    37                     {
    38                         //推送给用户
    39                         Clients.Client(Context.ConnectionId).addNewMessageToPage(JsonConverter.Serialize(Message));
    40                     }
    41                     else if(Depart.ID!=groupId)
    42                     {
    43                         //推送给用户
    44                         Clients.Client(Context.ConnectionId).addNewMessageToPage(JsonConverter.Serialize(Message));
    45                     }
    46                 }                               
    47             }
    48             catch(Exception ex)
    49             {
    50                 //推送系统消息
    51                 Clients.Client(Context.ConnectionId).addSysMessageToPage("系统消息:消息发送失败,请稍后再试!");
    52                 throw ex.InnerException;
    53             }            
    54         }

    发送私聊消息

     1 /// <summary>
     2         /// 发送给指定用户(单播)
     3         /// </summary>
     4         /// <param name="clientId">接收用户的连接ID</param>
     5         /// <param name="message">发送的消息</param>
     6         public void SendSingle(string clientId, string message)
     7         {
     8             try
     9             {
    10                 //接收用户连接为空
    11                 if (string.IsNullOrEmpty(clientId))
    12                 {
    13                     //推送系统消息
    14                     Clients.Client(Context.ConnectionId).addSysMessageToPage("系统消息:用户不存在!");
    15                 }
    16                 else
    17                 {
    18                     //消息用户主体
    19                     var UserOnline = UserOnlineManage.LoadListAll(p => p.ConnectId == Context.ConnectionId).FirstOrDefault();
    20                     //接收消息用户主体
    21                     var ReceiveUser = UserOnlineManage.LoadListAll(p => p.ConnectId == clientId).FirstOrDefault();
    22                     if (ReceiveUser == null)
    23                     {
    24                         //推送系统消息
    25                         Clients.Client(Context.ConnectionId).addSysMessageToPage("系统消息:用户不存在!");
    26                     }
    27                     else
    28                     {
    29                         //保存消息
    30                         ChatMessageManage.Save(new Domain.SYS_CHATMESSAGE() { FromUser = UserOnline.FK_UserId, MessageType = Common.Enums.ClsDic.DicMessageType["私聊"], MessageContent = message, MessageDate = DateTime.Now, MessageIP = Utils.GetIP(), ToGroup = UserOnline.SYS_USER.ID.ToString() });
    31                         //返回消息实体
    32                         var Message = new Message() { ConnectId = UserOnline.ConnectId, UserName = UserOnline.SYS_USER.NAME, UserFace = string.IsNullOrEmpty(UserOnline.SYS_USER.FACE_IMG) ? "/Pro/Project/User_Default_Avatat?name=" + UserOnline.SYS_USER.NAME.Substring(0, 1) : UserOnline.SYS_USER.FACE_IMG, MessageDate = DateTime.Now.GetDateTimeFormats('D')[1].ToString() + " - " + DateTime.Now.ToString("HH:mm:ss"), MessageContent = message, MessageType = "private", UserId = UserOnline.SYS_USER.ID };                                        
    33                         if (ReceiveUser.IsOnline)
    34                         {
    35                             //推送给指定用户
    36                             Clients.Client(clientId).addNewMessageToPage(JsonConverter.Serialize(Message));
    37                         }
    38                         //推送给用户
    39                         Clients.Client(Context.ConnectionId).addNewMessageToPage(JsonConverter.Serialize(Message));
    40                         
    41                     }
    42                 }
    43             }
    44             catch (Exception ex)
    45             {
    46                 //推送系统消息
    47                 Clients.Client(Context.ConnectionId).addSysMessageToPage("系统消息:消息发送失败,请稍后再试!");
    48                 throw ex.InnerException;
    49             }            
    50         }

    前台发送消息:

     1 $.connection.hub.start().done(function () {            
     2             chat.server.register('用户帐号', '用户密码');
     3             //文本框回车推送
     4             $("#sendMessage").keyup(function (event) {
     5                 if (event.keyCode == 13 || event.which == 13)
     6                 {
     7                     if ($.trim($(this).val()) == '' || $.trim($(this).val()).length < 1) {
     8                         $(this).val($.trim($(this).val()));
     9                         $(this).focus();
    10                         return false;
    11                     }
    12                     else {
    13                         //私聊
    14                         if ($.trim($("#person").val()) != '' && $.trim($("#person").val()).length > 1) {
    15                             chat.server.sendSingle($("#person").val(), $(this).val());
    16                         }
    17                         else {
    18                             chat.server.send($(this).val(), $("#group").val());
    19                         }
    20                         $(this).val("").focus();                       
    21                     }
    22                     
    23                 }
    24             });
    25             
    26         });

    前台接收消息:

     1 //接收服务器信息
     2         chat.client.addNewMessageToPage = function (message) {            
     3             var data = eval("(" + message + ")");
     4             var html = '';
    5 //处理消息

    19 $(html).appendTo(".chat-discussion"); 20 $('.chat-discussion').scrollTop($('.chat-discussion')[0].scrollHeight); 21 if(!$("#small-chat-box").hasClass("active")) 22 { 23 messagecount = messagecount + 1; 24 } 25 if (messagecount > 0) 26 { 27 $("#small-chat .badge").html(messagecount); 28 } 29 }; 30 //接收系统消息 31 chat.client.addSysMessageToPage = function (message) { 32 $('<div class=" col-xs-12 m-t-sm m-b-sm text-center sysmessage">' + message + '</div>').appendTo(".chat-discussion"); 33 $('.chat-discussion').scrollTop($('.chat-discussion')[0].scrollHeight); 34 };

    离线:

    上线:

    私聊:

    组聊:

    原创文章 转载请尊重劳动成果 http://yuangang.cnblogs.com

  • 相关阅读:
    Centos7 定时任务
    Linux启动配置文件和运行等级runlevel
    Linux 网卡命名规则
    将博客搬至CSDN
    Lua调用C++动态链接库.so
    使用shell脚本执行批量mongosh语句
    TCP和UDP详解
    经受时延的确认(Delay ACK)
    18张图带你了解衡量网络性能的四大指标:带宽、时延、抖动、丢包
    TCP学习
  • 原文地址:https://www.cnblogs.com/yuangang/p/5617704.html
Copyright © 2020-2023  润新知