一、線上聊天室 1、新建解決方案 SignalROnlineChatDemo 2、新建MVC項目 SignalROnlineChatDemo.Web (無身份驗證) 3、安裝SignalR PM> install-package Microsoft.AspNet.SignalR 4、 創建一個稱為 ...
一、線上聊天室
1、新建解決方案 SignalROnlineChatDemo
2、新建MVC項目 SignalROnlineChatDemo.Web
(無身份驗證)
3、安裝SignalR
PM> install-package Microsoft.AspNet.SignalR
4、 創建一個稱為 Startup.cs 的新類
1 public class Startup 2 { 3 public void Configuration(IAppBuilder app) 4 { 5 // 有關如何配置應用程式的詳細信息,請訪問 http://go.microsoft.com/fwlink/?LinkID=316888 6 app.MapSignalR(); 7 } 8 }
5、添加Hubs
1 public class ChatHub : Hub 2 { 3 public void Hello() 4 { 5 Clients.All.hello(); 6 } 7 }
6、Action/View
1 /// <summary> 2 /// 線上聊天室 3 /// </summary> 4 /// <returns></returns> 5 public ActionResult Chat(string groupName) 6 { 7 if (string.IsNullOrWhiteSpace(groupName)) 8 { 9 return Content("groupName is nllOrWhiteSpace"); 10 } 11 return View((object)groupName); 12 }
1 @model string 2 @{ 3 ViewBag.Title = "Chat"; 4 } 5 6 <style> 7 .chat-container div { 8 margin: 10px 0; 9 } 10 .dN { 11 display: none; 12 } 13 </style> 14 15 <h2>Chat <span id="chatRoomName"></span></h2> 16 17 <div class="chat-container"> 18 <ul id="discussion"></ul> 19 <div class="sendto-wrap dN"> 20 發送給: 21 <span></span> 22 </div> 23 <div class="sendcontent-wrap"> 24 <input type="text" name="message" /> 25 <input type="button" id="btnSendMessage" value="Send" /> 26 </div> 27 </div> 28 29 @section scripts{ 30 <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script> 31 <!-- Reference the autogenerated SignalR hub script. --> 32 <script src="~/signalr/hubs"></script> 33 <script type="text/javascript"> 34 $(function () { 35 //聊天室編號 36 var groupName = '@Model'; 37 //成員昵稱 38 var nickName = ''; 39 //成員聊天Id 40 var connectionId = ''; 41 42 //Reference the auto-generated proxy for the hub. 43 var chat = $.connection.chatHub; 44 45 $("#chatRoomName").html(groupName); 46 47 //Get the user name and store it to prepend to message 48 while (nickName == '' || $.trim(nickName) == '') { 49 nickName = prompt('Enter your name:', '') 50 $('#displayname').val(nickName); 51 } 52 53 $('#message').focus(); 54 55 }); 56 57 </script> 58 }
7、功能1:新成員加入,群發歡迎
1 /// <summary> 2 /// newcomer 進入聊天室 3 /// </summary> 4 /// <param name="groupName"></param> 5 public void JoinGroup(string groupName, string userNickName) 6 { 7 //對聊天室成員群發‘新成員加入’ 8 var conId = Context.ConnectionId; 9 10 Groups.Add(conId, groupName); 11 12 var psn = new ChatPerson() 13 { 14 ConnectionId = conId, 15 NickName = userNickName, 16 GroupName = groupName, 17 }; 18 19 Clients.Caller.setCallerInfo(psn); 20 //Clients.Group(groupName).welcome(psn); //不能廣播給自己,所以分成了兩句 21 Clients.Caller.welcome(psn); 22 Clients.Group(groupName, conId).welcome(psn); 23 24 }
1 //新成員身份信息(connectionId) 2 chat.client.setCallerInfo = function (psn) { 3 connectionId = psn.ConnectionId; 4 groupName = psn.groupName; 5 }; 6 //welcome newcomer 7 chat.client.welcome = function (psn) { 8 $("#discussion").append('<li><a href="javascript:;" data-conId="' + psn.ConnectionId + '">' + psn.NickName + '</a>加入了聊天室</li>'); 9 };
結果截圖:
8、功能2:群發
1 /// <summary> 2 /// newcomer進入聊天室,對聊天室成員群發‘新成員加入’ 3 /// </summary> 4 /// <param name="groupName"></param> 5 public void JoinGroup(string groupName, string userNickName) 6 { 7 var conId = Context.ConnectionId; 8 var psn = new ChatPerson() 9 { 10 ConnectionId = conId, 11 NickName = userNickName, 12 GroupName = groupName, 13 }; 14 15 //成員信息計入Redis中 16 //var redisClient = RedisManager.GetClient(); 17 //if (redisClient.Get<ChatPerson>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, psn.ConnectionId)) != null) 18 //{ 19 // //connected 20 // return; 21 //} 22 //redisClient.Set<ChatPerson>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, psn.ConnectionId), psn); 23 //redisClient.SaveAsync(); 24 using (var redisClient = RedisManager.GetClient()) 25 { 26 IRedisTypedClient<ChatPerson> psns = redisClient.As<ChatPerson>(); 27 if (psns.GetValue(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, psn.ConnectionId)) != null) 28 { 29 //connected 30 return; 31 } 32 psns.SetValue(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, psn.ConnectionId), psn); 33 } 34 35 Groups.Add(conId, groupName); 36 Clients.Caller.setCallerInfo(psn); 37 //Clients.Group(groupName).welcome(psn); //不能廣播給自己,所以分成了兩句 38 Clients.Caller.welcome(psn); 39 Clients.Group(groupName, conId).welcome(psn); 40 } 41 42 /// <summary> 43 /// 群發內容 44 /// </summary> 45 public void SendMessage(string message) 46 { 47 if (string.IsNullOrWhiteSpace(message)) 48 { 49 return; 50 } 51 var conId = Context.ConnectionId; 52 ChatPerson psn = null; 53 var redisClient = RedisManager.GetClient(); 54 if ((psn = redisClient.Get<ChatPerson>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, conId))) == null 55 || string.IsNullOrWhiteSpace(psn.GroupName) || string.IsNullOrWhiteSpace(psn.NickName) 56 ) 57 { 58 //invalid ConnectionId 59 return; 60 } 61 Clients.Group(psn.GroupName).sendMessage(conId, psn.NickName, message); 62 }
1 //群發內容 2 chat.client.sendMessage = function (sendFromConnectionId, sendFromNickName, message) { 3 $("#discussion").append('<li><a href="javascript:;" data-conId="' + sendFromConnectionId + '">' + sendFromNickName + '</a>:' + message + '</li>'); 4 };
結果截圖:
9、功能3:回覆
1 /// <summary> 2 /// 回覆(@) 3 /// </summary> 4 /// <param name="sendTo"></param> 5 /// <param name="message"></param> 6 public void SendMessageTo(string sendTo, string message) 7 { 8 if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(sendTo)) 9 { 10 return; 11 } 12 var connId = Context.ConnectionId; 13 if (connId == sendTo) 14 { 15 return; 16 } 17 ChatPerson curPerson = null; 18 ChatPerson desPerson = null; 19 var redisClient = RedisManager.GetClient(); 20 if ((curPerson = redisClient.Get<ChatPerson>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, connId))) == null 21 || string.IsNullOrWhiteSpace(curPerson.GroupName) || string.IsNullOrWhiteSpace(curPerson.NickName) 22 ) 23 { 24 //invalid ConnectionId 25 return; 26 } 27 if ((desPerson = redisClient.Get<ChatPerson>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, sendTo))) == null 28 || string.IsNullOrWhiteSpace(desPerson.GroupName) || string.IsNullOrWhiteSpace(desPerson.NickName) 29 ) 30 { 31 //invalid ConnectionId 32 return; 33 } 34 if (curPerson.GroupName != desPerson.GroupName) 35 { 36 return; 37 } 38 39 Clients.Group(curPerson.GroupName).sendMessageTo(curPerson.ConnectionId, curPerson.NickName, desPerson.ConnectionId, desPerson.NickName, message); 40 }
1 //at回覆 2 chat.client.sendMessageTo = function (fromConnId, fromNickName, toConnId, toNickName, message) { 3 $("#discussion").append('<li data-connId="' + fromConnId + '" data-nickName="' + fromNickName + '"><a href="javascript:;">' + fromNickName + '</a>對<a href="javascript:;">' + toNickName + '</a> 說:' + message + ' ' 4 + (fromConnId == connectionId ? '' : ' <a href="javascript:;" action="at">@他</a>') + '' + (fromConnId == connectionId ? '' : ' <a title="屏蔽其發言" href="javascript:;" action="shielding">屏蔽</a>') + '</li>'); 5 };
1 //發送 2 $("#btnSendMessage").click(function () { 3 var desConnId = $('.sendto-wrap a').attr('data-desConnId'); 4 if (!desConnId || desConnId.length == 0) { 5 //群發 6 chat.server.sendMessage($('[name=message]').val()); 7 } 8 else { 9 //回覆 10 chat.server.sendMessageTo(desConnId, $('[name=message]').val()); 11 } 12 $('.sendto-wrap').addClass('dN'); 13 $('.sendto-wrap a').attr('data-desConnId', ''); 14 $('[name=message]').val('').focus(); 15 }); 16 //at 17 $('#discussion').on('click', '[action=at]', function () { 18 var desConnId = $(this).closest('li').attr('data-connId'); 19 var desNickName = $(this).closest('li').attr('data-nickName'); 20 $('.sendto-wrap').removeClass('dN'); 21 $('.sendto-wrap a').attr('data-desConnId', desConnId).html(desNickName); 22 });
結果截圖:
10、功能4:私信
1 /// <summary> 2 /// 私信給 3 /// </summary> 4 /// <param name="sendTo"></param> 5 /// <param name="message"></param> 6 public void PrivateMessageTo(string sendTo, string message) 7 { 8 if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(sendTo)) 9 { 10 return; 11 } 12 var connId = Context.ConnectionId; 13 if (connId == sendTo) 14 { 15 return; 16 } 17 ChatPerson curPerson = null; 18 ChatPerson desPerson = null; 19 var redisClient = RedisManager.GetClient(); 20 if ((curPerson = redisClient.Get<ChatPerson>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, connId))) == null 21 || string.IsNullOrWhiteSpace(curPerson.GroupName) || string.IsNullOrWhiteSpace(curPerson.NickName) 22 ) 23 { 24 //invalid ConnectionId 25 return; 26 } 27 if ((desPerson = redisClient.Get<ChatPerson>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, sendTo))) == null 28 || string.IsNullOrWhiteSpace(desPerson.GroupName) || string.IsNullOrWhiteSpace(desPerson.NickName) 29 ) 30 { 31 //invalid ConnectionId 32 return; 33 } 34 if (curPerson.GroupName != desPerson.GroupName) 35 { 36 return; 37 } 38 Clients.Caller.myPrivateMessageTo(desPerson.ConnectionId, desPerson.NickName, message); 39 Clients.Client(sendTo).bePrivateMessageTo(curPerson.ConnectionId, curPerson.NickName, message); 40 }
1 //私信 2 $('#discussion').on('click', '[action=privateAt]', function () { 3 var desConnId = $(this).closest('li').attr('data-connId'); 4 var desNickName = $(this).closest('li').attr('data-nickName'); 5 $('.sendto-wrap span.sendto-to').html('私信給'); 6 $('.sendto-wrap').removeClass('dN'); 7 $('.sendto-wrap a').attr('data-desConnId', desConnId).attr('data-desAction', 'privateAt').html(desNickName); 8 });
1 //privateAt私信 2 //我發的 3 chat.client.myPrivateMessageTo = function (toConnId, toNickName, message) { 4 $("#discussion").append('<li data-connId="' + connectionId + '" data-nickName="' + nickName + '">我對<a href="javascript:;">' + toNickName + '</a> 說:' + message + ' ' 5 //+ getActionBlockHtml(connectionId) 6 ); 7 }; 8 //發給我的 9 chat.client.bePrivateMessageTo = function (fromConnId, fromNickName, message) { 10 $("#discussion").append('<li data-connId="' + fromConnId + '" data-nickName="' + fromNickName + '"><a href="javascript:;">' + fromNickName + '</a>對我私信說:' + message + ' ' 11 + getActionBlockHtml(fromConnId) 12 ); 13 };
結果截圖:
11、功能5:屏蔽
1 /// <summary> 2 /// 3 /// </summary> 4 public class PersonShielding 5 { 6 /// <summary> 7 /// 成員的ConnectionId 8 /// </summary> 9 public string ConnectionId { get; set; } 10 11 /// <summary> 12 /// 被屏蔽 我被哪些人屏蔽(這樣設計似乎不合理,但好用) 13 /// </summary> 14 public string[] BeShieldingByConnIdArr { get; set; } 15 }
1 /// <summary> 2 /// 屏蔽某人的發言 3 /// </summary> 4 /// <param name="desConId"></param> 5 public void Shielding(string desConnId) 6 { 7 if (string.IsNullOrWhiteSpace(desConnId)) 8 { 9 return; 10 } 11 var connId = Context.ConnectionId; 12 if (connId == desConnId) 13 { 14 return; 15 } 16 var redisClient = RedisManager.GetClient(); 17 ChatPerson curPerson = null; 18 ChatPerson desPerson = null; 19 if ((curPerson = redisClient.Get<ChatPerson>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, connId))) == null 20 || string.IsNullOrWhiteSpace(curPerson.GroupName) || string.IsNullOrWhiteSpace(curPerson.NickName) 21 ) 22 { 23 //invalid ConnectionId 24 return; 25 } 26 if ((desPerson = redisClient.Get<ChatPerson>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_ChatPerson, desConnId))) == null 27 || string.IsNullOrWhiteSpace(desPerson.GroupName) || string.IsNullOrWhiteSpace(desPerson.NickName) 28 ) 29 { 30 //invalid ConnectionId 31 return; 32 } 33 var personShielding = redisClient.Get<PersonShielding>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_PersonShielding, desConnId)); 34 if (personShielding == null) 35 { 36 personShielding = new PersonShielding() 37 { 38 ConnectionId = desConnId, 39 BeShieldingByConnIdArr = new string[] { connId } 40 }; 41 } 42 else 43 { 44 if (personShielding.BeShieldingByConnIdArr == null) 45 { 46 personShielding.BeShieldingByConnIdArr = new string[] { connId }; 47 } 48 else if (!personShielding.BeShieldingByConnIdArr.Contains(connId)) 49 { 50 personShielding.BeShieldingByConnIdArr = personShielding.BeShieldingByConnIdArr.Union(new string[] { connId }).ToArray(); 51 } 52 } 53 redisClient.Set<PersonShielding>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_PersonShielding, desConnId), personShielding); 54 redisClient.SaveAsync(); 55 56 Clients.Caller.shieldingSuccess(desConnId, desPerson.NickName); 57 }
1 var personShielding = redisClient.Get<PersonShielding>(string.Format(RedisKey.SignalROnlineChatDemoWebModels_PersonShielding, connId)); 2 if (personShielding != null && personShielding.BeShieldingByConnIdArr != null && personShielding.BeShieldingByConnIdArr.Length > 0) 3 { 4 //屏蔽我的 不發 5 Clients.Group(curPerson.GroupName, personShielding.BeShieldingByConnIdArr).sendMessage(connId, curPer