SignalR+MongoDB实现用户留言即时推送
前言:
最近写了一个项目,要实现即时通讯功能,在网上查了一下有两种常见的实现方式:SignalR和WebSocket,SignalR是封装好的一个类库,有三种传输模式:LongLooping(长轮询)、WebSocket、Forever Frame(隐藏框架的长请求连接),它会根据浏览器的环境自动选择合适的传输方式(比如说低版本的IE浏览器不支持WebSocket,SiganlR就会采用长轮询的方式传输)。SiganlR的介绍可以在百度搜一下有很多,这篇博客简单的介绍一下如何用SiganlR实现一个实时的消息推送功能。
一开始用户留言是存到SqlServer中的,考虑到用户留言价值相对较低,数据量大的特点,用MongoDB在性能上比较有优势(不用写Sql了,干活好快)
实现步骤:
1.安装SignalR
Install-Package Microsoft.AspNet.SignalR
安装成功后会系统会新增对应的js文件
2.创建Connections文件夹,存放永久连接类和Startup.cs
创建永久连接类:
代码:
public class ChatConnections : PersistentConnection { protected override Task OnConnected(IRequest request, string connectionId) { return null; } protected override Task OnReceived(IRequest request, string connectionId, string data) { return Connection.Broadcast(data); } }
创建startup类,如果项目中已经有了就不用创建了
代码:
public class Startup1 { public void Configuration(IAppBuilder app) { app.MapSignalR<ChatConnections>("/Connections/ChatConnections"); } }
3.用户发送留言
SignalR推送消息给后台->留言写入MongoDB
1.页面引入jquery.signalR-2.4.0.js和jquery
js:
<script src="~/layer/layer.js"></script> <script src="~/scripts/jquery-1.10.2.min.js"></script> <script src="~/scripts/jquery.signalR-2.4.0.js"></script> <script type="text/javascript"> $(function () { //获取连接 var connection = $.connection("/Connections/ChatConnections"); //监听消息,用户端不用做处理 connection.received(function (data) { }); // Wire up Send button to call NewContosoChatMessage on the server. connection.start().done(function () { $("#btn1").click(function () { layer.msg('确定发起留言?', { time: 0 //不自动关闭 , btn: ['确定', '取消'] , btn1: function (index) { //加载层 var index = layer.load(1, { shade: [0.1, '#fff'] }); $.ajax({ type: "post", url: "/User/Message/SendMessage", data: $('#form1').serialize(), }).success(function (message) { //消息推送 connection.send(message); layer.msg(message, { icon: 1 }); var index = parent.layer.getFrameIndex(window.name);//获取当前弹出层的层级 window.parent.location.reload();//刷新父页面 parent.layer.close(index);//关闭弹出层 }).fail(function (err) { layer.msg('系统错误,请稍后重试', { icon: 2 }); }) layer.close(index)//关闭加载层 }, btn2: function (index) { layer.close(); } }); }); }); }); </script>
控制器:
public async Task<JsonResult> SendMessage(MessageReq req) { SessionModel session = SessionInfo.GetSession(); var info = _mysqlRepository.GetUserInfo(session.UserCode); req.SendName = info.UserName; req.SendCode = info.UserCode; req.SendPhone = info.Phone; //写入MongoDB if (! await _mongoRepository.InsertMessage(req)) { return Json("留言失败"); } return Json("留言成功"); } #endregion
4.管理员接收留言:
SignalR监听用户发送留言,刷新页面时查询MongoDB里是否有未读留言
js:
<script src="~/scripts/jquery.signalR-2.4.0.min.js"></script> <script> $(function () { //监听用户发送留言 var connection = $.connection("/Connections/ChatConnections"); connection.received(function (data) { layer.closeAll(); layer.open({ type: 2, shade: [0], title: '您有新的留言', shadeClose: true, shade: false, area: ['280px', '215px'], content: ['/Manager/Home/Ifarme', 'no'], //iframe的url,no代表不显示滚动条 offset: 'rb' //右下角弹出 }); }); connection.start().done(function () { }); //刷新页面查询是否有未读留言 $.ajax({ type: "post", url: "/Manager/Home/QueryExist" }).success(function (message) { if (message == "Yes") { layer.open({ type: 2, shade: [0], title: '您有新的留言', shadeClose: true, shade: false, area: ['280px', '215px'], content: ['/Manager/Home/Ifarme', 'no'], //iframe的url,no代表不显示滚动条 offset: 'rb' //右下角弹出 }); } }).fail(function (err) { layer.msg('未能读取未读留言', { icon: 2 }); }) }); </script>
控制器:
/// <summary> /// 查询是否有未读留言 /// </summary> /// <returns></returns> public async Task<JsonResult> QueryExist() { var result = await _msg.QueryExist(); if (!result) { return Json("No"); } return Json("Yes"); }
点击留言标为已读:
/// <summary> /// 标为已读 /// </summary> /// <param name="id"></param> /// <returns></returns> public async Task<JsonResult> AlRead(string id) { if (! await _mongoRepository.AlRead(id)) { return Json("操作失败", JsonRequestBehavior.AllowGet); } return Json("成功", JsonRequestBehavior.AllowGet); }
到这里用户->管理员的实时消息推送就实现了
效果图:
写在最后:博主本人也是最近刚学SignalR,说的有不对的地方,请各位大佬指点,相互学习,在此我也会深入的学习SignalR,后续会继续分享SignalR的学习记录