参考:Tutorial: Getting Started with SignalR 2 and MVC 5
环境:vs2013,webapi2,entity framework6.0
实现效果:当用户上传一个文件时候,推送消息给关注此用户的其他用户,告知此用户上传了一个新的文件。
推送原理:当前端用户打开网页时候,SignalR 服务端会自动生成一个guid类型的ConnectionId。此ConnectionId用来连接确定用户端,用来确定发送给哪个当前在线用户。当要推送消息时候,后端方法会根据这个ConnectionId来调动用户端的js方法,同时传递数据,利用用户端的js完成消息推送。
前端添加:
<script src="http://xxxx.com/jquery-1.6.4.min.js"></script>
<script src="http://xxxx.com/jquery.signalR-2.2.0.js"></script>
<script src="http://xxxx.com/signalr/hubs"></script>
另:
在前端的js中要有回调方法,供后端推送消息时候调用。类似:
1 <script> 2 $(function () { 3 // Reference the auto-generated proxy for the hub. 4 var chat = $.connection.chatHub; 5 // Create a function that the hub can call back to display messages. 6 chat.client.addNewMessageToPage = function (name, message) { 7 // Add the message to the page. 8 $('#discussion').append('<li><strong>' + htmlEncode(name) 9 + '</strong>: ' + htmlEncode(message) + '</li>'); 10 }; 11 12 </script>
后端过程:
1、在nuget中安装Microsoft.AspNet.SignalR
2、在项目根目录下会自动生成一个Startup.cs的类文件。如下配置:
1 public void Configuration(IAppBuilder app) 2 { 3 // Branch the pipeline here for requests that start with "/signalr" 4 app.Map("/signalr", map => 5 { 6 // Setup the CORS middleware to run before SignalR. 7 // By default this will allow all origins. You can 8 // configure the set of origins and/or http verbs by 9 // providing a cors options with a different policy. 10 map.UseCors(CorsOptions.AllowAll); 11 var hubConfiguration = new HubConfiguration 12 { 13 // You can enable JSONP by uncommenting line below. 14 // JSONP requests are insecure but some older browsers (and some 15 // versions of IE) require JSONP to work cross domain 16 // EnableJSONP = true 17 }; 18 // Run the SignalR pipeline. We're not using MapSignalR 19 // since this branch already runs under the "/signalr" 20 // path. 21 map.RunSignalR(hubConfiguration); 22 }); 23 24 }
3、添加新建项: 类型为:SignalR Hub Class (v2)。名称:PushHub.cs
在 PushHub.cs中,继承Hub抽象类。
在此类中,写发送消息的方法。类似:
public void Send(List<PullMessageDto> data) { // Call the addNewMessageToPage method to update clients. //指定给某用户推送消息 Clients.Client(user.ConnectionId).broadcastMessage(message); //给所有当前在线用户推送消息 Clients.All.addNewMessageToPage(name, message); }
4、实现向指定用户推送消息。
这是在webApi2中,没有session,后端不保存用户是否在线状态。所以,这边当用户登录时候,前端把用户名和自动生成的ConnectionId发送到后端,后端保存到数据库中(用户名ConnectionId联合主键,每次登录都更新),当要推送的时候,就根据用户名查找ConnectionId,来实现定向推送。
在PushHub.cs中可以直接使用Clients类,但在其他类中,就得这样使用。
IHubContext _hubContext = GlobalHost.ConnectionManager.GetHubContext<PushHub>();
在其他类中代码:
1 public void PullMessage(string categoryId, string user) 2 { 3 ////查询订阅或关注用户 4 List<string> list = new List<string>(); 5 var temp = IMediameta.GetPullMessageUsers(categoryId, user); 6 IHubContext _hubContext = GlobalHost.ConnectionManager.GetHubContext<PushHub>(); 7 8 foreach (var item in temp) 9 { 10 var message = item; 11 var json = new JavaScriptSerializer().Serialize(message); 12 var connectionId = IMediameta.GetHubInfoByItCode(item.User); 13 14 if (!string.IsNullOrEmpty(connectionId)) 15 { 16 _hubContext.Clients.Client(connectionId).broadcastMessage(message); 17 } 18 } 19 }
前端还要有个broadcastMessage的js方法。参照以上addNewMessageToPage方法。
问题:
1、多服务器多数据库这边会出现推送问题,有些推送消息无法推送到。分为post服务器和get服务器,写数据库和读数据库。