写在前面:博主第一次写博文,菜鸟一枚,如果有什么写的不对,理解错误,还望各位轻喷。这个功能是博主最近项目开发的时候遇到的一个功能,在各种途径下学习,写这篇博文是为了给自己做个记录,同时也希望可以得到大家的矫正,大家一起进步!好了,废话不多说了,从SignalR开始!
首先是安装SignalR,SignalR在nuget上可以下载安装,在vs的工具里能找到nuget管理:
然后在搜索框里输入SignalR,就可以找到SignalR的安装文件,
然后安装就可以了,当然我查到还有另外一种安装方法,我就不再叙述了,有兴趣的可以搜一下。
安装的时候,有可能会出现这种错误:
这时请选中工程保证目标框架4.5以上:
然后再次安装即可,后面的就下一步下一步,接受之类的就可以了。
安装成功后在Script文件夹里多了两个js文件 后期使用的时候需要拖入。
然后想尝试添加控制器 添加视图测试的时候,启动项目报了个
未能加载文件或程序集“Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed”
的错,这时你需要在config文件中加些配置了:
在runtime的节点里面 加上一段:
如图:
加完后再启动项目,又发现了报了
The following errors occurred while attempting to load the app.
- No assembly found containing an OwinStartupAttribute.
- No assembly found containing a Startup or [AssemblyName].Startup class.
To disable OWIN startup discovery, add the appSetting owin:AutomaticAppStartup with a value of "false" in your web.config.
To specify the OWIN startup Assembly, Class, or Method, add the appSetting owin:AppStartup with the fully qualified startup class or configuration method name in your web.config.
的错误,看着意思是说项目里没有startup的类,我们知道MVC项目的启动很多相关是在App_Start文件夹里配置的,所以在这个文件夹里加一个startup.cs
如图:
如果是vs2015,建的是mvc6.0的话 就直接在Startup.Auth.cs里加上一句app.MapSignalR();就可以了 如果不加的话 网站启动的时候不会报错 但是在后面使用SignalR的时候会在前端一直报一个hub的js文件找不到,蛋疼... 在添加完startup文件后 网站终于可以正常启动了。
好了,SignalR安装完成,网站也跑起来了,接下来就是需求了,就实现上级领导给选择下级,给下级发送一个通知,下级能即时收到通知。用SignalR实现。首先,在SignalR的hub类中是有分组group的概念,我一开始的想法是能不能直接在上级领导选择下级的时候就放到一个group里面 然后再统一发送 后来发现 这不符合我的实际情况,因为我是需要在网站启动 用户登录之后 就加入客户端的监听之中,然后就是一直等待服务端推送了,也就是说在登录之后 就已经确定了group了,后期领导选择用户后 更改不了用户的分组group了(至少我没找到什么方法,当然如果你有办法,欢迎提出来!) 所以这样的话 我就选择在用户登录之后 将用户的唯一标识userId当做分组groupId 然后 自己去维护一个分组。
代码走起:
首先是要实现服务端的消息推送 就定义一个类实现hub接口:
//服务端代码
[HubName("chatHub")]
public class ChatHub : Hub
{
///
/// 全局唯一的用户集合
///
List
userList;
public ChatHub()
{
userList = SignalRSingler.CreateUserList();
}
List userIdList = new List();
public void AddToRoom(string groupId, string userName)
{
//将分组Id放到上下文中
Groups.Add(Context.ConnectionId, groupId);
//群发人员进入信息提示
Clients.Group(groupId, new string[0]).addUserIn(groupId, userName);
//将登陆后的所有用户放入用户集合中
userList.Add(new SignalRUserInfo() { ConnectId = Context.ConnectionId, GroupId = groupId, UserInfoId = groupId, UserName = userName });
}
///
/// 消息推送
///
/// 发送的内容
/// 用户名
/// 要推送的用户ID(前端获取后用,分隔)
public void Send(string detail, string userName, string selectUserId)
{
if (!string.IsNullOrEmpty(selectUserId))
{
userIdList = selectUserId.Split(',').ToList();
foreach (string str in userIdList)
{
if (userList.Any(c => c.UserInfoId == str))
{
//只发送用户选中的group
Clients.Group(str, new string[0]).addSomeMessage(detail, userName);
}
}
}
else
{
Clients.All.addSomeMessage(detail, userName);//群发给所有
}
}
}
客户端代码:
首先要引用 两个js文件 分别是:
注意第二个引用,并不是具体的物理文件来的,直接引用就可以了
当然这一段最好是放在用户登录成功后回调就将用户的userId添加到客户端连接中,然后保持监听
$(function(){
var chat = $.connection.chatHub;
chat.hubName = 'chatHub';
$.connection.hub.logging = true;//启动signalr状态功能
$.connection.hub.start(function () {
//客户端链接成功后添加到监听
chat.server.addToRoom('@ViewData["userId"]', '@ViewData["loginName"]');
});
})
//这里要注意 在创建好connection后 可以直接调用服务端的方法 但是:经过调试发现(博主踩过的坑) 服务端用的是帕斯卡命名法,而前端js用的是驼峰命名法,所以js的同名方法,首字母要小写,否则会报方法没有定义!
添加监听后,实现当接收到推送消息后的代码:
//回调 接收到消息
chat.client.addSomeMessage = function ( detail, userName) {
$("#corner_dialog").show("slow");
var content = "【时间:" + GetDateTimeNow() + "】
" + "【发送人:" + userName + "】" + "【内容:" + detail + "】"
$("#hid_Detail").val(content);
};
这些就是一般用户在首页监听的代码,接下来是上级领导发送消息:
//发送消息
$("#send").click(function () {
var detail = $("#txtArea_command").val();
var userName = '@ViewBag.loginName';
var selectUserId = $("#hid_SelectUser").val();
//调用服务端的send方法 传入相关的参数
chat.server.send(detail, userName, selectUserId);
$("#txtArea_command").val("");
});
好啦 以上就是选择用户推送消息的基本代码 我实现选择用户的思路主要是SignalR不能在领导选中用户时,动态修改用户加入的group(或许是我不懂),所以我就选择用每个用户唯一的UserId作为groupId 然后用一个List去维护自己的分组。 SignalR感觉用起来还是很爽的 实时的消息推送 前端直接调用后端方法 也可以很方便的实现前后端参数传递。
好了 第一篇博文 写得很烂 通用性可能也不好, 有什么写得不好,想得不好的,实现的不好的,如果各位有更好的想法,或技术希望各位多多指教!
最后要感谢博客园的月下之神,主要借鉴了他的文章,原文链接:http://www.cnblogs.com/yxzs/p/5642774.html