[Azure雲端服務及應用開發]_群組移除用戶功能)_part5



圖片摘自:


佩脫拉克:我是凡人,我只要求凡人的幸福。



有添加至群組後看起來還差從群組移除的功能
用戶可能突然想換群組或是進錯群組之類的....
可能白天是個worker 晚上下班後是其他人的husband 或 wife 



新增Azure Function
依舊選
Http trigger 跟 Anonymous 

在來函數型態結構還有前置作業大致上跟AddToGroup都差不多
只有後續移除部分
GroupAction 的 Enum要記得改成Remove


透過TableQuery去取得User Entity集合 (已經Linq 過濾出特定User)
隨後進行Iterate Delete


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using KYChat.Messages;
using Microsoft.WindowsAzure.Storage.Table;
using KYChat.Functions.Models;

namespace KYChat.Functions
{
    public static class RemoveFromGroup
    {
        [FunctionName("RemoveFromGroup")]
        public static async Task Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            [SignalR(HubName = "chat")] IAsyncCollector<SignalRGroupAction> signalRGroupActions,
            [Table("Users",Connection ="StorageConnectionString")] CloudTable userTable,
            ILogger log)
        {
            var message = new JsonSerializer()
                .Deserialize<UserConnectedMessage>(new JsonTextReader(new StreamReader(req.Body)));

            //message.IsEntered = true;
            await signalRGroupActions.AddAsync(new SignalRGroupAction
            {
                ConnectionId = message.Token,
                UserId = message.Sender,
                GroupName = message.GroupName,
                Action = GroupAction.Remove
            });

            TableQuery<UserEntity> rangeQuery = new TableQuery<UserEntity>()
                .Where(TableQuery.GenerateFilterCondition("RowKey"
                , QueryComparisons.Equal,
                message.Sender));

            foreach(var entity in await userTable.ExecuteQuerySegmentedAsync(rangeQuery, null))
            {
                TableOperation deleteOperation = TableOperation.Delete(entity);
                TableResult result = await userTable.ExecuteAsync(deleteOperation);
            }

        }
    }
}


之後
我們又要擴充聊天服務的規格了
一致性開發流程
Step1. Config 多增設Web Api Endpoint


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
using System;
using System.Collections.Generic;
using System.Text;

namespace KYChat.Core
{
    public static class Config
    {
        public static string MainEndPoint = "http://localhost:7071";
        public static string NegotiateEndPoint = $"{MainEndPoint}/api/negotiate";
        public static string MessageEndPoint = $"{MainEndPoint}/api/Messages";
        public static string AddToGroupEndPoint = $"{MainEndPoint}/api/AddToGroup";
        public static string LeaveGroupEndPoint = $"{MainEndPoint}/api/RemoveFromGroup";
    }
}


Step2.擴充Service規格及相應具體實作
IChatService
添加Task LeaveChannelAsync(UserConnectedMessage message);


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
using KYChat.Core.Models;
using KYChat.Messages;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace KYChat.Core.Services
{
    public interface IChatService
    {
        bool IsConnected { get; }
        string ConnectionToken { get; set; }
        Task InitAsync(string userId);
        Task DisconnectionAsync();
        Task SendMessageAsync(ChatMessage message);
        Task JoinChannelAsync(UserConnectedMessage message);
        Task<List<Room>> GetRooms();
        Task LeaveChannelAsync(UserConnectedMessage message);
    }
}




ChatService補實作


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public async Task LeaveChannelAsync(UserConnectedMessage message)
        {
            if (!IsConnected)
                return;
            message.Token = ConnectionToken;

            var strJson = JsonConvert.SerializeObject(message);

            var content = new StringContent(strJson, Encoding.UTF8, "application/json");

            await httpClient.PostAsync(Config.LeaveGroupEndPoint, content);

            await SendMessageAsync(message);
        }

Config戳的EndPoint改成LeaveGroupEndPoint


接著我們要進到Azure Portal Table Preview來做移除功能的測試
點進Storage Account後
選 Storage Explorer (preview)
選Tables下剛剛創建的Users



可以看到剛才在測試的連線資料都有Insert進去

選中其中一筆可以進行刪除動作(會在跳確認的視窗可以反悔)
按Shift不放可複選




或者按下Edit也可進行編輯更新


這裡我先清空所有Entity
怕超出用量要收費 >~<

到Clinet 端 console專案修改多一個
判斷當user輸入leave時候的處理區塊


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using KYChat.Core.Services;
using KYChat.Messages;
using System;
using System.Threading.Tasks;

namespace KYChat.Client
{
    class Program
    {
        static ChatService myService;
        static string userName;
        static string room;

        static async Task Main(string[] args)
        {
            Console.WriteLine("User Name:");
            userName = Console.ReadLine();

            myService = new ChatService();
            myService.OnReceiveMessage += MyService_OnReceiveMessage;

            await myService.InitAsync(userName);
            Console.WriteLine("You are connected now !!");

            await JoinRoom();

            bool IsKeepGoing = true;
            do
            {
                var text = Console.ReadLine();
                if (text.Trim().ToLower().Equals("exit"))
                {
                    await myService.DisconnectionAsync();
                    IsKeepGoing = false;
                }
                else if (text.Trim().ToLower().Equals("leave"))
                {
                    var message = new UserConnectedMessage(userName, room);
                    await myService.LeaveChannelAsync(message);
                    await JoinRoom();
                }
                else
                {
                    var message = new SimpleTextMessage(userName)
                    {
                        Text = text
                    };
                    await myService.SendMessageAsync(message);
                }
            } while (IsKeepGoing);


        }

        private static async Task JoinRoom()
        {
            var rooms = await myService.GetRooms();
            Console.WriteLine("===聊天群組列表===");
            foreach (var room in rooms)
            {
                Console.WriteLine(room.Name);
            }
            Console.WriteLine("請輸入想進入的聊天群組:");
            room = Console.ReadLine();
            var message = new UserConnectedMessage(userName, room);
            await myService.JoinChannelAsync(message);
        }

        private static void MyService_OnReceiveMessage(object sender, Core.EventHandlers.MessageEventArgs e)
        {
            if (e.Message.Sender == userName)
                return;
            if (e.Message.TypeInfo.Name == nameof(SimpleTextMessage))
            {
                var simpleText = e.Message as SimpleTextMessage;
                var message = $"{simpleText.Sender}: {simpleText.Text}";
                Console.WriteLine(message);
            }
            else if (e.Message.TypeInfo.Name == nameof(UserConnectedMessage))
            {
                var userConnected = e.Message as UserConnectedMessage;
                string message = string.Empty;
                if (userConnected.IsEntered)
                {
                    message = $"{userConnected.Sender} 已進入群組";
                }
                else
                {
                    message = $"{userConnected.Sender} 已離開群組";
                }
                Console.WriteLine(message);
            }
        }
    }
}


測試情況也可正常Work啦
可喜可賀!






留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

(2021年度)駕訓學科筆試準備題庫歸納分析_法規是非題