public async Task Invoke(HttpContext context) { if (!context.WebSockets.IsWebSocketRequest || context.Request.Path != "/wschat") { await _next.Invoke(context); return; } CancellationToken ct = context.RequestAborted; WebSocket currentSocket = await context.WebSockets.AcceptWebSocketAsync(); var socketId = Guid.NewGuid().ToString(); _sockets.TryAdd(socketId, currentSocket); Console.WriteLine($"info: chat socket connected."); string response; MessageModel message; while (true) { if (ct.IsCancellationRequested) { break; } try { response = await currentSocket.ReceiveStringAsync(ct); } catch (Exception exp) { Console.WriteLine($"info: socket aborted.\nMore info: {exp.Message}"); break; } if (string.IsNullOrEmpty(response)) { if (currentSocket.State != WebSocketState.Open) { break; } continue; } try { if (response == "GetMessages") { var savedMessages = messages.ToArray(); if (savedMessages.Length > 0) { foreach (var ms in savedMessages) { await _sockets[socketId].SendStringAsync(ms, ct); } } await _sockets[socketId].SendStringAsync(_sockets.Count, ct); continue; } else { message = JsonConvert.DeserializeObject <MessageModel>(response); messages.AddNewMessage(message); } } catch { continue; } foreach (var socket in _sockets) { if (socket.Value.State != WebSocketState.Open) { continue; } await socket.Value.SendStringAsync(message, _sockets.Count, ct); } } _sockets.TryRemove(socketId, out _); if (currentSocket.State != WebSocketState.Aborted) { await currentSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", ct); } currentSocket.Dispose(); Console.WriteLine($"WebSocket disconnect from chat: {socketId}"); }