ASP.NET Core SignalR - How to Join & Remove a Group and Send To a Group From Client


In this post, we will discuss how to send a message to a group using SignalR. To demonstrate the complete setup, I have created a basic solution for SignalR where messages can be sent and received to all clients through the browser.

In this project, we will implement the usage of groups so that users can join a group and send messages from a client. In our example, we have created a JavaScript client.

On the browser, users will select which SignalR group they wish to join using a button, ensuring each communication server instance represents a group.

If you are looking for one-to-one chat in ASP.NET Core using SignalR, then you should take a look at that post.

In our example we are going to discuess about the below point

  • How to join a group using SignalR.
  • How to send a message to a group using SignalR.
  • How to exit a group using SignalR.

GroupChat Hub Code

using Microsoft.AspNetCore.SignalR;
using System.Diagnostics;

namespace SignalRGroips.HubGroup
{
    public class GroupChat : Hub
    {
        public override Task OnDisconnectedAsync(Exception exception)
        {
            return base.OnDisconnectedAsync(exception);
        }
        public override Task OnConnectedAsync()
        {
            return base.OnConnectedAsync();
        }
        //Create a group for each user to chat in chat i group
        public void JoinGroup(string groupId)
        {
            Groups.AddToGroupAsync(Context.ConnectionId, groupId);
        }
        //If user want to exist from the group
        public void ExistFromGroup(string groupId)
        {
            Groups.RemoveFromGroupAsync(Context.ConnectionId, groupId);
        }
        //Send message to user Group
        public async Task SendMessageToGroup(string groupId,string message)
        {
            await Clients.Group(groupId).SendAsync("ReceiveMessageClient", groupId, message);
        }
    }
}
The OnConnectedAsync method is overridden to perform some action when a client connects to the hub. In that function if you want some customer logic you can wirte here.

The `OnDisconnectedAsync` method handles disconnection events from clients, similar to the `OnConnectedAsync` method. With these events, you can remove users from your database if you are maintaining an online user list.

The JoinGroup function allows a client to join a specific group identified by groupId. It uses the Groups.AddToGroupAsync method to add the client's connection to the specified group.

The ExistFromGroup method allows a client to leave a group identified by groupId. It uses the Groups.RemoveFromGroupAsync method to remove the client's connection from the specified group.
The 

SendMessageToGroup funtion is used to send a message to all clients belonging to a specific group. It accepts the groupId and message parameters and uses the Clients.Group(groupId).SendAsync to send the message to all clients in the specified group. 

The method sends a message with the event name "ReceiveMessageClient", along with the groupId and message as parameters.

We are providing functionality for managing groups and sending messages to clients within those groups using SignalR in an ASP.NET Core application.
Let's write the client-side code.
Above code provides a simple interface for selecting a group and sending a message to that group using SignalR in an ASP.NET Core web application.

The SendMessageToGroup() function retrieves the message and group ID from the UI elements, invokes the SendMessageToGroup method on the SignalR hub, and clears the message input field.

Dropdown element for choosing a group. The Dropdown element contains two elements representing different teams (football and cricket).


Sender Client
<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
</head>
<body>

    <h1>
        How to implement groups in SignalR in an ASP.NET Core web application.
    </h1>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.0.1/css/toastr.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.0.1/js/toastr.js"></script>
    <label>Select Team Group</label>
    <br />
    <select id="ddlgroup">
        <option value="footbaalteam">Foot Team</option>
        <option value="cricketteam">Cricket Team</option>
    </select>
    <br />
    <textarea rows="3" cols="30" id="textgroup"></textarea>
    <br />
    <button type="button" onclick="SendMessageToGroup()">Send Message To Group</button>
    <script type="text/javascript">
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("https://localhost:7089/GroupChat")
            .configureLogging(signalR.LogLevel.Information)
            .build();

        async function start() {
            try {
                await connection.start();
                console.log("SignalR Connected.");
            } catch (err) {
                console.log(err);
                setTimeout(start, 5000);
            }
        };

        connection.onclose(async () => {
            await start();
        });
        // Start the connection.
        start();
        async function SendMessageToGroup() {
            try {
                var message = $("#textgroup").val();
                var GroupId = $("#ddlgroup").val();
                await connection.invoke("SendMessageToGroup", GroupId, message);
                $("#textgroup").text("");
            } catch (err) {
                console.error(err);
            }
        }
    </script>
</body>
</html>
Group User
The JoinGroup() function is defined to handle joining and leaving groups based on user selection. It invokes the ExistFromGroup method to leave the current group, then joins the selected group.

Event handlers are attached to the ReceiveMessageClient event to display received messages using the toastr library, and to the onclose event of the SignalR connection to handle connection closures by restarting the connection.


Below code provides a simple interface for joining a group and receiving messages from that group using SignalR in an ASP.NET Core application.


<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
</head>
<body>

    <h1>
        Footbaal Team Group
    </h1>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.0.1/css/toastr.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.0.1/js/toastr.js"></script>
    <label>User Group</label>
    <select id="ddlgroup">
        <option value="footbaalteam">Football Team</option>
        <option value="cricketteam">Cricket Team</option>
    </select>
    <button type="button" onclick="JoinGroup()">Join Group</button>
    <script type="text/javascript">
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("https://localhost:7089/GroupChat")
            .configureLogging(signalR.LogLevel.Information)
            .build();
        async function start() {
            try {
                await connection.start();
                console.log("SignalR Connected.");
                await connection.invoke("JoinGroup", $("#ddlgroup").val());
            } catch (err) {
                console.log(err);
                setTimeout(start, 5000);
            }
        };
        async function JoinGroup() {
            var groupId = $("#ddlgroup").val();
            if (groupId == "footbaalteam") {
                await connection.invoke("ExistFromGroup", "cricketteam");
                await connection.invoke("JoinGroup", "footbaalteam");
            }
            else {
                await connection.invoke("ExistFromGroup", "footbaalteam");
                await connection.invoke("JoinGroup", "cricketteam");
            }
            var text = $("#ddlgroup  option:selected").text();
            $("h1").text(text)
        }
        connection.on("ReceiveMessageClient", async (groupId, message) => {
            toastr.success(message);
        });
        connection.onclose(async () => {
            await start();
        });
        // Start the connection.
        start();
    </script>
</body>
</html>
Now let's open the sender client in one browser tab and open the group user HTML in another browser tab or open it in a new incognito tab.
And let's select two different groups for each user, click on the 'Join' button, and then send a notification message from the sender user.
Let's send a message to the football team.Only user with football group get the notification


Let's send a message to the cricket team.Only user with cricket group get the notifcation

Select the football group for both clients and then send a message to the group, both user get the notification as both join the footbaal group