前言,如今這世道寫篇帖子沒個前言真很差意思發出來。本貼的主要內容來自於本人在以前項目中所開發的一個小功能,用於OA中的即時通信。因爲當時走的太急,忘記把代碼拿出來。想一想這已是大半年前的事情了,時間過了這麼久,在當時最新的SignalR2.0.1到如今已經變成了2.2。昨天晚上特意熬了個夜,從新又把它寫出來作了一個小小的Demo。固然我只是大天然的搬運工,這個SignalR即時通信功能裏面有一些前端的類庫不是我本身寫的。我只是改吧改吧~~在此鳴謝 @賢心,是他的幾條庫才使得個人這個功能如此酷炫。前言猝!html
沒個GIF的演示我會拿出來秀?前端
看上去是否是感受還能夠? 那下面我講解一下開發步驟。jquery
首先咱們打開VS2015(固然其它的版本也能夠。我只是趕了個時髦,有天心血來潮就給安裝了),再依次點擊[文件]-[新建]-[項目]後彈出以下界面:app
咱們選擇ASP.NET Web應用程序,而且將項目名稱完善好,選擇好項目保存路徑。再點擊肯定:ide
這裏爲了讓等會的操做更加簡單我直接選擇了一個ASP.NET 4.5的 Empty 模板。並把下方的「爲如下項目添加文件夾和核心引用」選擇MVC。再點擊肯定:函數
好了到這裏風雲突變狂風大做…一個活生生擁有着MVC核心引用和文件夾的項目已經展示在眼前。下面咱們就往項目中加入等會要使用到的SignalR。工具
這裏用到了NuGet,網上也有不少資源講解怎麼使用這個。我這裏只大概講解一下。首先打開[工具]-[NuGet 程序包管理器]-[管理解決方案的 NuGet 程序包]spa
接下來在出現的界面中將程序包源改爲:聯機,而後搜索SignalR。接下來自行解決~.~.net
因爲此時的項目仍是一個Empty的項目,須要經過Startup類來配置OWIN程序,因此要在項目中加入一個OWIN Startup類3d
建立好以後,再在Configuration函數中加入app.MapSignalR();
好了下面,咱們再爲SignalR建立一個集線器Hubs,個人習慣是在項目中建立一個Hubs目錄,而後把須要建立的HubClass放到裏面。下面先在項目中建立一個Hubs目錄,再在目錄上單擊右鍵選擇[添加]-[新建項]選擇[SignalR 集線器類]
點擊肯定,再把新建的HubClass中的Hello函數幹掉。而後在類上增長一個特性:[HubName("systemHub")]
。既然是要聊天那麼天然離不開用戶,爲了方便管理我創建了一個用戶的實體類UserDetail
1 /// <summary> 2 /// 用戶細節 3 /// </summary> 4 public class UserDetail 5 { 6 /// <summary> 7 /// 鏈接ID 8 /// </summary> 9 public string ConnectionId { get; set; } 10 /// <summary> 11 /// 用戶ID 12 /// </summary> 13 public string UserID { get; set; } 14 /// <summary> 15 /// 用戶名 16 /// </summary> 17 public string UserName { get; set; } 18 /// <summary> 19 /// 用戶部門 20 /// </summary> 21 public string DeptName { get; set; } 22 /// <summary> 23 /// 登陸時間 24 /// </summary> 25 public DateTime LoginTime { get; set; } 26 }
既然用戶類有了,那麼咱們能夠在Hub裏面建立一個用戶池,用來管理在線用戶。
1 public static List ConnectedUsers = new List();
如今用戶池有了,下面須要實現三個功能就能進行登陸、上線、下線、私聊操做了。這是下面的邏輯處理代碼:
1 /// <summary> 2 /// 登陸連線 3 /// </summary> 4 /// <param name="userID">用戶ID</param> 5 /// <param name="userName">用戶名</param> 6 /// <param name="deptName">部門名</param> 7 public void Connect(string userID, string userName, string deptName) 8 { 9 var id = Context.ConnectionId; 10 11 if (ConnectedUsers.Count(x => x.ConnectionId == id) == 0) 12 { 13 if (ConnectedUsers.Count(x => x.UserID == userID) > 0) 14 { 15 var items = ConnectedUsers.Where(x => x.UserID == userID).ToList(); 16 foreach (var item in items) 17 { 18 Clients.AllExcept(id).onUserDisconnected(item.ConnectionId, item.UserName); 19 } 20 ConnectedUsers.RemoveAll(x => x.UserID == userID); 21 } 22 //添加在線人員 23 ConnectedUsers.Add(new UserDetail { ConnectionId = id, UserID = userID, UserName = userName, DeptName = deptName, LoginTime = DateTime.Now }); 24 25 // 反饋信息給登陸者 26 Clients.Caller.onConnected(id, userName, ConnectedUsers); 27 28 // 通知全部用戶,有新用戶鏈接 29 Clients.AllExcept(id).onNewUserConnected(id, userID, userName, deptName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); 30 31 } 32 else 33 { 34 35 } 36 } 37 38 /// <summary> 39 /// 發送私聊 40 /// </summary> 41 /// <param name="toUserId">接收方用戶鏈接ID</param> 42 /// <param name="message">內容</param> 43 public void SendPrivateMessage(string toUserId, string message) 44 { 45 string fromUserId = Context.ConnectionId; 46 var toUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == toUserId); 47 var fromUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == fromUserId); 48 49 if (toUser != null && fromUser != null) 50 { 51 // send to 52 Clients.Client(toUserId).receivePrivateMessage(fromUserId, fromUser.UserName, message); 53 54 // send to caller user 55 //Clients.Caller.sendPrivateMessage(toUserId, fromUser.UserName, message); 56 } 57 else 58 { 59 //表示對方不在線 60 Clients.Caller.absentSubscriber(); 61 } 62 } 63 64 /// <summary> 65 /// 離線 66 /// </summary> 67 public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled) 68 { 69 var item = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId); 70 if (item != null) 71 { 72 Clients.All.onUserDisconnected(item.ConnectionId, item.UserName); //調用客戶端用戶離線通知 73 ConnectedUsers.Remove(item); 74 } 75 return base.OnDisconnected(stopCalled); 76 }
我這裏寫的邏輯只是一個簡單的示例,這個能夠根據本身的想法和需求任意發揮。發揮時遇到問題也歡迎在留言一塊兒交流。服務端代碼完了,下面開始創建客戶端代碼。
到了這裏咱們貌似尚未新建頁面,訪問會報404! 那麼咱們先在Controllers目錄上單擊右鍵選擇[添加]-[控制器]在彈出的界面中選擇[MVC5控制器]
名字取成Home。而後把@賢心大神的彈層庫等等庫引用進來。把JS也引用進來。 在這時也能看到在Scripts目錄下面有了幾個SignalR的js文件。那麼既然咱們建好Controller了下面就在HomeController的IndexAction上面單擊右鍵選擇[添加視圖]在調用的時候須要注意的是要引用SignalR的內容:
1 <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script> 2 <script src="~/signalr/hubs"></script>
至於調用的方法也是比較簡單的啦,下面附上簡單的示例。更多詳細的處理能夠下載個人DEMO源碼進行參考。
1 //實例SystemHub,首字母必須小寫才能調用 2 var systemHub = $.connection.systemHub; 3 //開始連接到集線器 4 $.connection.hub.start().done(function () { 5 //調用服務端函數Connect(首字母小寫)以及傳遞客戶端參數進行上線操做 6 systemHub.server.connect(userid, username, deptname); 7 }); 8 //新用戶上線 9 systemHub.client.onNewUserConnected = function (id, userID, userName, deptName, loginTime) { 10 //定義onNewUserConnected客戶端函數供服務端調用 11 }; 12 //用戶離線 13 systemHub.client.onUserDisconnected = function (id, userName) { 14 //定義onUserDisconnected客戶端函數供服務端調用 15 }; 16 //發送消息時,對方已不在線 17 systemHub.client.absentSubscriber = function () { 18 //定義absentSubscriber客戶端函數供服務端調用 19 }; 20 //接收消息 21 systemHub.client.receivePrivateMessage = function (fromUserId, userName, message) { 22 //定義receivePrivateMessage客戶端函數供服務端調用 23 }; 24 //發送消息 25 systemHub.server.sendPrivateMessage(ChatCore.nowchat.id, data.content);
好了,關於MVC中使用SignalR的介紹也詳細描述了,我只是拋磚引玉把本身之前開發的功能進行分享以及本身的溫習。具體的源碼在下方進行下載,若是以爲內容不錯,歡迎留言獻花以示鼓勵~~
源碼下載:FangsiChat.zip
本文來自 放肆雷特 | 鋒哥的技術博客