今天要來個小型的實作一個連線名單,連線名單可以讓你知道目前在線的人有誰(廢話),之前的範例都是在進入時傳送訊息給所有人,如果是中途進來的人,是無從得知目前有哪些人在線上
,如果要做一個聊天室沒這基本的功能也太爛了吧!XD
一樣使用Day3的範例來做,沒有的點這裡
製作一個名單容器和容器Service
我們先要製作一個容器,把目前上線的人資訊都存下來,至於要存哪些呢?我覺得使用者名稱
和連接ID
是一定需要的,再來就是上線的時間點,大概就這些,先建立一個ConUserModel.cs
,
並建立一個Class當容器。
1
2
3
4
5
6
7
8
9
10
11
12
|
using System;
using System.Collections.Generic;
namespace CoreWeb.Models
{
public class ConUserModel
{
public string connectID { get; set; }
public string username { get; set; }
public DateTime onlineTime { get; set; }
}
}
|
再來建立ConUserService
,這邊我建立在同一個檔案內,在內部建立一個List
泛型內部裝剛剛建立的ConUserModel
,建立新增及移除List的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class ConUserService
{
private List<ConUserModel> _list;
public ConUserService()
{
_list = new List<ConUserModel>();
}
public List<ConUserModel> AddList(ConUserModel user)
{
_list.Add(user);
return _list;
}
public List<ConUserModel> RemoveList(string connectID)
{
for (int i = 0; i < _list.Count; i++)
{
if (_list[i].connectID == connectID)
_list.Remove(_list[i]);
}
return _list;
}
}
|
再到Starp.cs
註冊Service
1
2
3
4
5
|
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ConUserService>();
services.AddSignalR();
}
|
再來到我們建立一個Hub裡面引用Core.Models
Hub內宣告List<ConUserMode>
,建構子裡面接收從Servie傳過來的List<ConUserMode>
,在載入到Hub內的List變數
1
2
3
4
5
6
7
8
9
10
11
|
namespace CoreWeb.Hubs
{
public class ChatHub : Hub
{
private ConUserService conUserList;
public ChatHub(ConUserService conUserService)
{
conUserList = conUserService;
}
}
}
|
後端連線斷線的處理
後端每當有人連線或斷線時,都要重新傳送一份名單給所有使用者,所以得要在OnConnectedAsync
和OnDisconnectedAsync
處理,但是OnConnectedAsync
裡面不能接參數,所以我們改用
連線後,再加入的群組的方式,首先寫加入群組的方法,群組假設叫TestGroup
1
2
3
4
5
6
7
8
9
10
|
public async void AddConUserList(string user)
{
var _user = new ConUserModel();
_user.username = user;
_user.connectID = Context.ConnectionId;
_user.onlineTime = DateTime.Now;
await Groups.AddToGroupAsync(Context.ConnectionId, "TestGroup");
await Clients.Group("TestGroup").SendAsync("GetConList", conUserList.AddList(_user));
}
|
程式碼大概就是建立一個ConUserModel
相關資料塞進去,加入群組後再加入上線名單。
然後切斷連線時,要通知群組所有人更新連線名單
1
2
3
4
5
|
public override async Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
await Clients.Group("TestGroup").SendAsync("GetConList", conUserList.RemoveList(Context.ConnectionId));
}
|
前端表現處理
我們先建立一個連線名單的select html element
,記得加入multiple
屬性讓它展開
1
|
<select id="ConList" multiple></select>
|
在連線的方法成功之後加入群組
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
document.getElementById('conOpenBtn').onclick = function () {
connection.start().then(function() {
console.log('start');
var user = document.getElementById("name").value;
// 加入群組
connection.invoke("AddConUserList", user).catch(function (err) {
return console.error(err.toString());
});
}).catch(function (err) {
return console.error(err.toString());
});
}
|
更新名單的方法每次都要清空List,再重新填入Server傳回來的名單
1
2
3
4
5
6
7
8
9
10
|
connection.on("GetConList", function (ConList) {
console.log(ConList);
_ConList.innerHTML = '';
for (var i = 0; i < ConList.length; i++) {
var user = document.createElement("option");
user.text = ConList[i].username;
_ConList.appendChild(user);
}
})
|
DEMO
今天大概就這些,雖然它只是一個小組件,但是之後的實作都能套用到它,明天會會來個比較難一點的。
範例下載