Implementation Code of Rich and Colorful Message Pushing Mode in SignalR

Time:2019-9-2

In the last SignalR article, we demonstrated how to implement simple chat room functions through SignalR; in the principle of simplicity is beauty, we will also talk about the concept of users and groups in SignalR, understand these basic knowledge will help to better develop applications based on SignalR, through users and sub-users. Group understanding further expands the management of users and groups, as well as various ways of message pushing, in preparation for full access to SignalR.

1. Users

In ignalR, a user represents a connection, a user represents a connection, and a “system user” can create multiple connection identities and send messages to all connections of a user through a function hub; for example, a “system user” has multiple connections, which are Web connections and AndroId hands, respectively. Client-to-client connections, IOS mobile client connections, or other client connections, and “System User” logs on to these clients and creates multiple connections at the same time; by default, these connections are associated with the user ID through ClaimTypes. NameIdentifier in Claims Principal.

** Note: User identifiers are case-sensitive. In order to achieve multiple connections for a customer, this example also implements a simple Claims Identity-based login interface, which is a surprise.

1.1 User Connection Management

In order to intuitively observe that users can have multiple connections, a local static object is needed to store user connections.

public class WeChatHub : Hub
 {
  public Dictionary<string, List<string>> UserList { get; set; } = new Dictionary<string, List<string>>();

  public void Send(ChatMessage body)
  {
   Clients.All.SendAsync("Recv", body);
  }

  public override Task OnConnectedAsync()
  {
   var userName = this.Context.User.Identity.Name;
   var connectionId = this.Context.ConnectionId;
   if (!UserList.ContainsKey(userName))
   {
    UserList[userName] = new List<string>();
    UserList[userName].Add(connectionId);
   }
   else if (!UserList[userName].Contains(connectionId))
   {
    UserList[userName].Add(connectionId);
   }
   Console. WriteLine ("Wow, someone came in: {0}, {1}, {2}), this. Context. User Identifier, this. Context. User. Identity. Name, this. Context. ConnectionId);
   return base.OnConnectedAsync();
  }

  public override Task OnDisconnectedAsync(Exception exception)
  {
   var userName = this.Context.User.Identity.Name;
   var connectionId = this.Context.ConnectionId;
   if (UserList.ContainsKey(userName))
   {
    if (UserList[userName].Contains(connectionId))
    {
     UserList[userName].Remove(connectionId);
    }
   }

   Console. WriteLine ("Come on, someone's running: {0}", this. Context. ConnectionId);
   return base.OnDisconnectedAsync(exception);
  }
 }

The above code contains an internal member, UserList, to store each connection of the user. When the user makes a SignalR connection, the current connection is stored in the UserList. When the connection is disconnected, the current connection is deleted from the UserList. This implements a simple user connection management.

In the above code, the current user nickname is based on VAR userName = this. Context. User. Identity. Name; this line of code is obtained by implementing a simple User Identity login to obtain this user nickname, and then writing the User information to Cookie before finally passing var userName = this. Con. Text. User. Identity. Name; get the current login user nickname (familiar with the ID login process should not be strange to students, in fact, I rarely use ID authentication)

1.2 Send a message to a single user


  [Authorize(Roles = "User")]
  [HttpPost("SendToUser")]
  public async Task<IActionResult> SendToUser([FromBody] UserInfoViewModel model)
  {
   ChatMessage message = new ChatMessage()
   {
    Type = 1,
    Content = model.Content,
    UserName = model.UserName
   };

   if (this.chatHub.UserList.ContainsKey(model.UserName))
   {
    var connections = this.chatHub.UserList[model.UserName].First();
    await this.chatHub.Clients.Client(connections).SendAsync("Recv", new object[] { message });
   }

   return Json(new { Code = 0 });
  }

In UserController, the interface SendToUser is defined above. The client passes in the user nickname and message. Then the server will search the connection information of the target user according to the members of ChatHub. UserList. Finally, the message is pushed to the connection of the target client through SendAsync.

2. Grouping

The concept of grouping is similar to chat room. Each room is an independent grouping. Users can choose to join room A or room B. If business permits, a user can also join multiple groupings (rooms). By using grouping to manage users, one or more chats can be realized. In Sky Room, users can join groups or delete users from groups (similar to leaving the room), where users concurrently concurrently refer to the “system users” in the real sense, but refer to the signal R connections created by the system users.

** Note: SignalR does not retain group membership when a connection is re-initiated after disconnection, and must rejoin the group.

The following code demonstrates how to operate on a group and how to operate on a group. It mainly includes three aspects:

2.1 Add Groups


 public async Task AddToGroupAsync(string groupName)
  {
   await Groups.AddToGroupAsync(this.Context.ConnectionId, groupName);
  }

2.2 Departure from Groups


 public async Task RemoveFromGroupAsync(string groupName)
  {
   await Groups.RemoveFromGroupAsync(this.Context.ConnectionId, groupName);
  }

2.3 Send messages to specified groups


 public async Task SendToGroupAsync(string groupName, ChatMessage message)
  {
   await Clients.Group(groupName).SendAsync(groupName, new object[] { message });
  }

The operation of grouping is very simple. It’s almost a line of code. I have to say that Microsoft’s encapsulation is very good.

3. Other Ways of Pushing Messages by SignalR

Through the above study of users and groups, and then to expand the learning of other ways of pushing messages, it is very good to understand and get started. There are also many ways of pushing messages in SignalR, they are:

3.1 All (full station push)

3.2 Others

3.3 Other InGroup

3.4 AllExcept (everyone except the specified list)

3.5 Demo Code

List<string> blackList = new List<string>();
  public async Task OtherSendAsync(ChatMessage body)
  {
   // Sending messages to all connections currently connected to Hub is equivalent to broadcasting
   await Clients.All.SendAsync("Recv", body);

   // Send a message to the current connection object
   await Clients.Caller.SendAsync("Recv", body);

   // Send messages to all other connected clients except those currently connected
   await Clients.Others.SendAsync("Recv", body);

   // Find all currently connected clients (excluding themselves) and push them messages if they have joined the group
   await Clients.OthersInGroup("groupName").SendAsync("Recv", body);

   // Send messages to everyone except BlackList
   await Clients.AllExcept(blackList).SendAsync("Recv", body);
  }

4. A simple example

This sample code contains two simple interfaces

4.1 Logon

4.2 Send messages in various ways

Concluding remarks

Recently, I am working on an open source project, which is still in the trial stage. I am going to write a WIKI to see if you are interested. This SingalR series can only be updated from time to time. Sorry.

Demo Code Download

Hosted to GitHub Warehouse

https://github.com/lianggx/Examples/tree/master/SignalR/Ron.SignalRLesson2

The above is the whole content of this article. I hope it will be helpful to everyone’s study, and I hope you will support developpaer more.

Recommended Today

Write a package for parsing abnormal JSON strings – fbbk-json

F [beep] [beep] K JSON Parse a package of abnormal JSON strings. install $ npm install fbbk-json Use This package has only one function: var fJSON = require(“fbbk-json”); fJSON.parse(A_JSON_STRING); however This package supports the following JSON strings (that is, what we usually declare in javascript, without quotation marks). Raise a chestnut. ‘{foo”:”bar”,”baz”: true} < – […]