MVC中使用SignalR


MVC中使用SignalR打造酷炫實用的即時通訊功能附源碼

 

前言,現在這世道寫篇帖子沒個前言真不好意思發出來。本貼的主要內容來自於本人在之前項目中所開發的一個小功能,用於OA中的即時通訊。由於當時走的太急,忘記把代碼拿出來。想想這已經是大半年前的事情了,時間過了這么久,在當時最新的SignalR2.0.1到現在已經變成了2.2。昨天晚上特地熬了個夜,重新又把它寫出來做了一個小小的Demo。當然我只是大自然的搬運工,這個SignalR即時通訊功能里面有一些前端的類庫不是我自己寫的。我只是改吧改吧~~在此鳴謝 @賢心,是他的幾條庫才使得我的這個功能如此酷炫。前言猝!

最終效果演示

沒個GIF的演示我會拿出來秀?

看上去是不是感覺還可以? 那下面我講解一下開發步驟。

創建MVC項目

首先我們打開VS2015(當然其它的版本也可以。我只是趕了個時髦,有天心血來潮就給安裝了),再依次點擊[文件]-[新建]-[項目]后彈出如下界面:

我們選擇ASP.NET Web應用程序,並且將項目名稱完善好,選擇好項目保存路徑。再點擊確定:

這里為了讓等會的操作更加簡單我直接選擇了一個ASP.NET 4.5的 Empty 模板。並把下方的“為以下項目添加文件夾和核心引用”選擇MVC。再點擊確定:

好了到這里風雲突變狂風大作…一個活生生擁有着MVC核心引用和文件夾的項目已經展現在眼前。下面我們就往項目中加入等會要使用到的SignalR。

為MVC項目在NuGet中引用SignalR

這里用到了NuGet,網上也有很多資源講解怎么使用這個。我這里只大概講解一下。首先打開[工具]-[NuGet 程序包管理器]-[管理解決方案的 NuGet 程序包]

接下來在出現的界面中將程序包源改成:聯機,然后搜索SignalR。接下來自行解決~.~

使用SignalR

由於此時的項目還是一個Empty的項目,需要通過Startup類來配置OWIN程序,所以要在項目中加入一個OWIN Startup類

創建好之后,再在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 }
復制代碼

我這里寫的邏輯只是一個簡單的示例,這個可以根據自己的想法和需求任意發揮。發揮時遇到問題也歡迎在留言一起交流。服務端代碼完了,下面開始建立客戶端代碼。

客戶端調用SignalR

到了這里我們貌似還沒有新建頁面,訪問會報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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM