SignalR實現線上聊天室功能(歡迎、發送、回覆、私信、屏蔽)

来源:http://www.cnblogs.com/frozenzhang/archive/2016/04/24/5406773.html
-Advertisement-
Play Games

一、線上聊天室 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>&nbsp;說:' + message + ' '
4                     + (fromConnId == connectionId ? '' : '&nbsp;&nbsp;&nbsp;<a href="javascript:;" action="at">&#64;他</a>') + '' + (fromConnId == connectionId ? '' : '&nbsp;&nbsp;&nbsp;<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>&nbsp;說:' + 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

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 傳入一個cid,返回一個數組類型數據,在傳入數組中的cid,返回子類別數組數據,直到沒有子類別 例子: 將: [ { "cid","123", name:"標題1" }, { "cid","1234", name:"標題1" }, { "cid","1234", name:"標題1" }, { "c ...
  • [源碼下載] 背水一戰 Windows 10 (9) - 資源: 資源限定符概述, 資源限定符示例 作者:webabcd介紹背水一戰 Windows 10 之 資源 資源限定符概述 資源限定符示例 示例1、資源限定符概述Resource/Qualifiers/Summary.xaml Resourc ...
  • 代碼: using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Configuration; using System.Da ...
  • EF6引入一個彈性連接的功能,也就是允許重新嘗試執行失敗的資料庫操作。某些複雜的場景中,可能需要啟用或停用重試執行的策略,但是EF框架暫時尚未提供直接的設置開關,將來可能會加入這種配置。幸運的是,很容易自己實現該設置功能。 最簡單的註冊執行策略的方法是通過基於代碼的配置。下麵代碼是一個典型的配置類, ...
  • Chapter 05 變數的更多內容 5.1類型轉換 1.無論什麼類型,所有的數據都是一系列的位,即一組0和1。變數的含義是通過解釋這些數據的方式來傳達的。最簡單的示例是char類型,這種類型用一個數字表示Unicode字元集中的一個字元。實際上,這個數字與ushort的存儲方式相同 他們都是存儲0 ...
  • AnkhSVN是一款在VS中管理Subversion的插件,您可以在VS中輕鬆的提交、更新、添加文件,而不用在命令行或資源管理器中提交。而且該插件屬於開源項目。AnkhSvn安裝下載完畢後,進行安裝,安裝嚮導安裝即可,如下步驟。【步驟1】安裝界面,見圖。 【步驟2】安裝成功 AnkhSvn連接Vis ...
  • ASP.NET 頁運行時,此頁將經歷一個生命周期,在生命周期中將執行一系列處理步驟。這些步驟包括初始化、實例化控制項、還原和維護狀態、運行事件處理程式代碼以及進行呈現。瞭解頁生命周期非常重要,因為這樣做您就能在生命周期的合適階段編寫代碼,以達到預期效果。此外,如果您要開發自定義控制項,就必須熟悉頁生命周 ...
  • 距離上一篇OpenAuth.net的文章已經有5個多月了,在這段時間里項目得到了很多朋友的認可,開源中國上面的Star數接近300,於是堅定了我做下去的信心。最近稍微清閑點,正式推出1.0版,併在阿裡雲上部署了一個線上演示(文章結尾處給出線上演示鏈接)。相比剛開始時的版本,現在整個架構已經穩定,系統 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...