Asp.NET MVC 使用 SignalR 实现推送功能二(Hubs 在线聊天室 获取保存用户信息)
简单介绍
关于SignalR的简单实用 请参考 Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室)
在上一篇中,我们只是介绍了简单的消息推送,今天我们来修改一下,实现保存消息,历史消息和用户在线
由于,我这是在一个项目(【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目 目录索引)的基础上做的,所以使用到的一些借口和数据表,不详细解析,只是介绍一下思路和实现方式,供大家参考
用户登录注册信息
当用户登录之后,我们注册一下用户的信息,我们在ChatHub中 新建一个方法 Register(用户帐号,用户密码)
前台js调用这个方法实现用户注册
- $.connection.hub.start().done(function () {
- chat.server.register('用户帐号', '用户密码');
- });
Register方法的实现:
- /// <summary>
- /// 用户登录注册信息
- /// </summary>
- /// <param name="id"></param>
- public void Register(string account,string password)
- {
- try
- {
- //获取用户信息
- var User = UserManage.Get(p => p.ACCOUNT == account);
- if (User != null && User.PASSWORD == password)
- {
- //更新在线状态
- var UserOnline = UserOnlineManage.LoadListAll(p => p.FK_UserId == User.ID).FirstOrDefault();
- UserOnline.ConnectId = Context.ConnectionId;
- UserOnline.OnlineDate = DateTime.Now;
- UserOnline.IsOnline = true;
- UserOnline.UserIP = Utils.GetIP();
- UserOnlineManage.Update(UserOnline);
- //超级管理员
- if (User.ID == ClsDic.DicRole["超级管理员"])
- {
- //通知用户上线
- Clients.All.UserLoginNotice("超级管理员:" + User.NAME + " 上线了!");
- }
- else
- {
- //获取用户一级部门信息
- var Depart = GetUserDepart(User.DPTID);
- if (Depart != null && !string.IsNullOrEmpty(Depart.ID))
- {
- //添加用户到部门群组 Groups.Add(用户连接ID,群组)
- Groups.Add(Context.ConnectionId, Depart.ID);
- //通知用户上线
- Clients.All.UserLoginNotice(Depart.NAME + " - " + CodeManage.Get(m => m.CODEVALUE == User.LEVELS && m.CODETYPE == "ZW").NAMETEXT + ":" + User.NAME + " 上线了!");
- }
- }
- //刷新用户通讯录
- Clients.All.ContactsNotice(JsonConverter.Serialize(UserOnline));
- }
- }
- catch(Exception ex)
- {
- Clients.Client(Context.ConnectionId).UserLoginNotice("出错了:" + ex.Message);
- throw ex.InnerException;
- }
- }
用户上线通知,大家可以在对话框内已系统消息的方式提示,我这里是一个toastr插件的提示
- //用户上线通知
- chat.client.UserLoginNotice = function (message) {
- if ($("#LoginNotice").prop("checked")) { toasSuccess.message_t(message); }
- };
这里面有个判断,如果用户允许提醒,就提示,如果不允许,就不提示,就是个checkbox
当用户登录后,刷新其它用户通讯录用户的在线状态,离线用户排到底部,并且如果用户离线,点击用户的时候,提示用户离线发送邮件还是离线消息
- //通讯录用户上下线
- chat.client.ContactsNotice = function (message) {
- var data = eval("(" + message + ")");
- if (!data.IsOnline) {
- var current = $("#charUser-" + data.FK_UserId).addClass("offline");
- var parentId = current.parent().parent().prop("id");
- current.remove().appendTo($("#" + parentId + " .panel-body"));
- }else
- {
- var current = $("#charUser-" + data.FK_UserId).removeClass("offline").attr("data-connectid", data.ConnectId);
- var parentId = current.parent().parent().prop("id");
- current.insertBefore($("#" + parentId + " .panel-body .offline").eq());
- }
- $(".panel-body .chat-user").click(function () {
- if ($(this).hasClass("offline")) {
- var MailId = $(this).attr("data-Email");
- var ConnectId = $(this).attr("data-connectid");
- var UserName = $(this).attr("data-username");
- 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); } });
- }
- else {
- ChatPerson($(this).attr("data-connectid"), $(this).attr("data-username"));
- }
- });
- };
在线:
离线:
用户离线
我们重写OnDisconnected方法,当用户离线时,更新用户状态 同时刷新其它用户通讯录用户在线状态
- //使用者离线
- public override Task OnDisconnected(bool stopCalled)
- {
- //更新在线状态
- var UserOnline = UserOnlineManage.LoadListAll(p => p.ConnectId == Context.ConnectionId).FirstOrDefault();
- UserOnline.ConnectId = Context.ConnectionId;
- UserOnline.OfflineDate = DateTime.Now;
- UserOnline.IsOnline = false;
- UserOnlineManage.Update(UserOnline);
- //获取用户信息
- var User = UserManage.Get(p => p.ID == UserOnline.FK_UserId);
- Clients.All.UserLogOutNotice(User.NAME + ":离线了!");
- //刷新用户通讯录
- Clients.All.ContactsNotice(JsonConverter.Serialize(UserOnline));
- return base.OnDisconnected(true);
- }
前台离线通知
- //用户离线通知
- chat.client.UserLogOutNotice = function (message) {
- if ($("#LogOutNotice").prop("checked")) { toasInfo.message_t(message); }
- };
获取历史消息
我是在用户登录的时候获取用户消息的,大家可以放到其它逻辑中
Register方法添加用户历史消息
- /// <summary>
- /// 用户登录注册信息
- /// </summary>
- /// <param name="id"></param>
- public void Register(string account,string password)
- {
- try
- {
- //获取用户信息
- var User = UserManage.Get(p => p.ACCOUNT == account);
- if (User != null && User.PASSWORD == password)
- {
- //更新在线状态
- var UserOnline = UserOnlineManage.LoadListAll(p => p.FK_UserId == User.ID).FirstOrDefault();
- UserOnline.ConnectId = Context.ConnectionId;
- UserOnline.OnlineDate = DateTime.Now;
- UserOnline.IsOnline = true;
- UserOnline.UserIP = Utils.GetIP();
- UserOnlineManage.Update(UserOnline);
- //获取历史消息
- int days = Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["HistoryDays"]);
- DateTime dtHistory = DateTime.Now.AddDays(-days);
- var ChatMessageList = ChatMessageManage.LoadAll(p => p.MessageDate > dtHistory);
- //超级管理员
- if (User.ID == ClsDic.DicRole["超级管理员"])
- {
- //通知用户上线
- Clients.All.UserLoginNotice("超级管理员:" + User.NAME + " 上线了!");
- var HistoryMessage = ChatMessageList.OrderBy(p=>p.MessageDate).ToList().Select(p => new
- {
- UserName = UserManage.Get(m => m.ID == p.FromUser).NAME,
- 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(, ) : UserManage.Get(m => m.ID == p.FromUser).FACE_IMG,
- MessageType=GetMessageType(p.MessageType),
- p.FromUser,
- p.MessageContent,
- MessageDate = p.MessageDate.GetDateTimeFormats('D')[].ToString() + " - " + p.MessageDate.ToString("HH:mm:ss"),
- ConnectId = UserOnlineManage.LoadListAll(m => m.SYS_USER.ID == p.FromUser).FirstOrDefault().ConnectId
- }).ToList();
- //推送历史消息
- Clients.Client(Context.ConnectionId).addHistoryMessageToPage(JsonConverter.Serialize(HistoryMessage));
- }
- else
- {
- //获取用户一级部门信息
- var Depart = GetUserDepart(User.DPTID);
- if (Depart != null && !string.IsNullOrEmpty(Depart.ID))
- {
- //添加用户到部门群组 Groups.Add(用户连接ID,群组)
- Groups.Add(Context.ConnectionId, Depart.ID);
- //通知用户上线
- Clients.All.UserLoginNotice(Depart.NAME + " - " + CodeManage.Get(m => m.CODEVALUE == User.LEVELS && m.CODETYPE == "ZW").NAMETEXT + ":" + User.NAME + " 上线了!");
- //用户历史消息
- int typeOfpublic = Common.Enums.ClsDic.DicMessageType["广播"];
- int typeOfgroup = Common.Enums.ClsDic.DicMessageType["群组"];
- int typeOfprivate = Common.Enums.ClsDic.DicMessageType["私聊"];
- 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
- {
- UserName = UserManage.Get(m => m.ID == p.FromUser).NAME,
- 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(, ) : UserManage.Get(m => m.ID == p.FromUser).FACE_IMG,
- MessageType = GetMessageType(p.MessageType),
- p.FromUser,
- p.MessageContent,
- MessageDate = p.MessageDate.GetDateTimeFormats('D')[].ToString() + " - " + p.MessageDate.ToString("HH:mm:ss"),
- ConnectId = UserOnlineManage.LoadListAll(m => m.SYS_USER.ID == p.FromUser).FirstOrDefault().ConnectId
- }).ToList();
- //推送历史消息
- Clients.Client(Context.ConnectionId).addHistoryMessageToPage(JsonConverter.Serialize(HistoryMessage));
- }
- }
- //刷新用户通讯录
- Clients.All.ContactsNotice(JsonConverter.Serialize(UserOnline));
- }
- }
- catch(Exception ex)
- {
- Clients.Client(Context.ConnectionId).UserLoginNotice("出错了:" + ex.Message);
- throw ex.InnerException;
- }
- }
前台:
- //接收历史信息
- chat.client.addHistoryMessageToPage = function (message) {
- var data = eval("(" + message + ")");
- var html = '';
- for(var i=;i<data.length;i++)
- {
- //处理消息
- }
- $(html).appendTo(".chat-discussion");
- $('<div class=" col-xs-12 m-t-sm m-b-sm text-center sysmessage"> — 以上是历史消息 — </div>').appendTo(".chat-discussion");
- };
发送广播、组播消息
- /// <summary>
- /// 发送消息(广播、组播)
- /// </summary>
- /// <param name="message">发送的消息</param>
- /// <param name="message">发送的群组</param>
- public void Send(string message,string groupId)
- {
- try
- {
- //消息用户主体
- var UserOnline = UserOnlineManage.LoadListAll(p => p.ConnectId == Context.ConnectionId).FirstOrDefault();
- //广播
- if(string.IsNullOrEmpty(groupId))
- {
- //保存消息
- ChatMessageManage.Save(new Domain.SYS_CHATMESSAGE() { FromUser = UserOnline.FK_UserId, MessageType = Common.Enums.ClsDic.DicMessageType["广播"], MessageContent = message, MessageDate = DateTime.Now, MessageIP = Utils.GetIP() });
- //返回消息实体
- 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(, ) : UserOnline.SYS_USER.FACE_IMG, MessageDate = DateTime.Now.GetDateTimeFormats('D')[].ToString() + " - " + DateTime.Now.ToString("HH:mm:ss"), MessageContent = message, MessageType = "public", UserId = UserOnline.SYS_USER.ID };
- //推送消息
- Clients.All.addNewMessageToPage(JsonConverter.Serialize(Message));
- }
- //组播
- else
- {
- //保存消息
- 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 });
- //返回消息实体
- 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(, ) : UserOnline.SYS_USER.FACE_IMG, MessageDate = DateTime.Now.GetDateTimeFormats('D')[].ToString() + " - " + DateTime.Now.ToString("HH:mm:ss"), MessageContent = message, MessageType = "group", UserId = UserOnline.SYS_USER.ID };
- //推送消息
- Clients.Group(groupId).addNewMessageToPage(JsonConverter.Serialize(Message));
- //如果用户不在群组中则单独推送消息给用户
- var Depart = GetUserDepart(UserOnline.SYS_USER.DPTID);
- if(Depart==null)
- {
- //推送给用户
- Clients.Client(Context.ConnectionId).addNewMessageToPage(JsonConverter.Serialize(Message));
- }
- else if(Depart.ID!=groupId)
- {
- //推送给用户
- Clients.Client(Context.ConnectionId).addNewMessageToPage(JsonConverter.Serialize(Message));
- }
- }
- }
- catch(Exception ex)
- {
- //推送系统消息
- Clients.Client(Context.ConnectionId).addSysMessageToPage("系统消息:消息发送失败,请稍后再试!");
- throw ex.InnerException;
- }
- }
发送私聊消息
- /// <summary>
- /// 发送给指定用户(单播)
- /// </summary>
- /// <param name="clientId">接收用户的连接ID</param>
- /// <param name="message">发送的消息</param>
- public void SendSingle(string clientId, string message)
- {
- try
- {
- //接收用户连接为空
- if (string.IsNullOrEmpty(clientId))
- {
- //推送系统消息
- Clients.Client(Context.ConnectionId).addSysMessageToPage("系统消息:用户不存在!");
- }
- else
- {
- //消息用户主体
- var UserOnline = UserOnlineManage.LoadListAll(p => p.ConnectId == Context.ConnectionId).FirstOrDefault();
- //接收消息用户主体
- var ReceiveUser = UserOnlineManage.LoadListAll(p => p.ConnectId == clientId).FirstOrDefault();
- if (ReceiveUser == null)
- {
- //推送系统消息
- Clients.Client(Context.ConnectionId).addSysMessageToPage("系统消息:用户不存在!");
- }
- else
- {
- //保存消息
- 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() });
- //返回消息实体
- 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(, ) : UserOnline.SYS_USER.FACE_IMG, MessageDate = DateTime.Now.GetDateTimeFormats('D')[].ToString() + " - " + DateTime.Now.ToString("HH:mm:ss"), MessageContent = message, MessageType = "private", UserId = UserOnline.SYS_USER.ID };
- if (ReceiveUser.IsOnline)
- {
- //推送给指定用户
- Clients.Client(clientId).addNewMessageToPage(JsonConverter.Serialize(Message));
- }
- //推送给用户
- Clients.Client(Context.ConnectionId).addNewMessageToPage(JsonConverter.Serialize(Message));
- }
- }
- }
- catch (Exception ex)
- {
- //推送系统消息
- Clients.Client(Context.ConnectionId).addSysMessageToPage("系统消息:消息发送失败,请稍后再试!");
- throw ex.InnerException;
- }
- }
前台发送消息:
- $.connection.hub.start().done(function () {
- chat.server.register('用户帐号', '用户密码');
- //文本框回车推送
- $("#sendMessage").keyup(function (event) {
- if (event.keyCode == || event.which == )
- {
- if ($.trim($(this).val()) == '' || $.trim($(this).val()).length < ) {
- $(this).val($.trim($(this).val()));
- $(this).focus();
- return false;
- }
- else {
- //私聊
- if ($.trim($("#person").val()) != '' && $.trim($("#person").val()).length > ) {
- chat.server.sendSingle($("#person").val(), $(this).val());
- }
- else {
- chat.server.send($(this).val(), $("#group").val());
- }
- $(this).val("").focus();
- }
- }
- });
- });
前台接收消息:
- //接收服务器信息
- chat.client.addNewMessageToPage = function (message) {
- var data = eval("(" + message + ")");
- var html = '';
- //处理消息
- $(html).appendTo(".chat-discussion");
- $('.chat-discussion').scrollTop($('.chat-discussion')[].scrollHeight);
- if(!$("#small-chat-box").hasClass("active"))
- {
- messagecount = messagecount + ;
- }
- if (messagecount > )
- {
- $("#small-chat .badge").html(messagecount);
- }
- };
- //接收系统消息
- chat.client.addSysMessageToPage = function (message) {
- $('<div class=" col-xs-12 m-t-sm m-b-sm text-center sysmessage">' + message + '</div>').appendTo(".chat-discussion");
- $('.chat-discussion').scrollTop($('.chat-discussion')[].scrollHeight);
- };
离线:
上线:
私聊:
组聊:
原创文章 转载请尊重劳动成果 http://yuangang.cnblogs.com
Asp.NET MVC 使用 SignalR 实现推送功能二(Hubs 在线聊天室 获取保存用户信息)的更多相关文章
- Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室)
简介 ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端 ...
- Asp.NET websocket,Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室)
ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知消息及 ...
- 在 Asp.NET MVC 中使用 SignalR 实现推送功能 [转]
在 Asp.NET MVC 中使用 SignalR 实现推送功能 罗朝辉 ( http://blog.csdn.net/kesalin ) CC许可,转载请注明出处 一,简介 Signal 是微软支持 ...
- MVC 中使用 SignalR 实现推送功能
MVC 中使用 SignalR 实现推送功能 一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Pus ...
- 史上最全面的SignalR系列教程-3、SignalR 实现推送功能-集线器类实现方式
1.概述 通过前两篇 史上最全面的SignalR系列教程-1.认识SignalR 史上最全面的SignalR系列教程-2.SignalR 实现推送功能-永久连接类实现方式 文章对SignalR的介绍, ...
- 使用 SignalR 实现推送功能
百度搜索:使用 SignalR 实现推送功能
- Asp.NET MVC 中使用 SignalR 实现推送功能
一,简介Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请 ...
- 在 Asp.NET MVC 中使用 SignalR 实现推送功能
一,简介Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请 ...
- 史上最全面的SignalR系列教程-2、SignalR 实现推送功能-永久连接类实现方式
1.概述 通过上篇史上最全面的SignalR系列教程-1.认识SignalR文章的介绍,我们对SignalR技术已经有了一个全面的了解.本篇开始就通过SignalR的典型应用的实现方式做介绍,例子虽然 ...
随机推荐
- 重新认识了下Entity Framework
什么是Entity Framework Entity Framework是一个对象关系映射O/RM框架. Entity Framework让开发者可以像操作领域对象(domain-specific o ...
- ASP.NET Core 中文文档目录
翻译计划 五月中旬 .NET Core RC2 如期发布,我们遂决定翻译 ASP.NET Core 文档.我们在 何镇汐先生. 悲梦先生. 张仁建先生和 雷欧纳德先生的群中发布了翻译计划招募信息,并召 ...
- jQuery幻灯片插件autoPic
原文地址:Jquery自定义幻灯片插件 插件效果图: 演示地址:autoPic项目地址:autoPic 欢迎批评指正!
- JAVA FreeMarker工具类
FreeMarkerUtil.java package pers.kangxu.datautils.utils; import java.io.File; import java.io.StringW ...
- python之最强王者(9)——函数
1.Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但 ...
- 分页插件--根据Bootstrap Paginator改写的js插件
刚刚出来实习,之前实习的公司有一个分页插件,和后端的数据字典约定好了的,基本上是看不到内部是怎么实现的,新公司是做WPF的,好像对于ASP.NET的东西不多,导师扔了一个小系统给我和另一个同事,指了两 ...
- Android—应用程序开机自启
android开机时候会发送开机广播,我们想要收到广播知道手机开机,才能启动我们的应用程序. 首先要在配置文件中添加相应权限: <uses-permission android:name=&qu ...
- 如何使用dos命令打开当前用户、当前日期、当前时间以及当前用户加当前时间?
1.dos命令安装mysqld --stall.启动net start mysql.进入MySQL数据库mysql -uroot -p后,输入select user();当前用户 select cur ...
- Express 教程 01 - 入门教程之经典的Hello World
目录: 前言 一.Express?纳尼?! 二.开始前的准备工作 三.测试安装之经典的Hello World 四.使用express(1)来生成一个应用程序 五.说明 前言: 本篇文章是建立在Node ...
- NOT IN 和NOT EXISTS
今天写了一个简单的NOT IN语句,结果跟预期大相径庭,百度之发现深坑一个,遂录之. 登陆账户表logins code name status a admin N b guest N c member ...