AspNetCore.Docs/aspnet/signalr/overview/guide-to-the-api/mapping-users-to-connection...

8.0 KiB

uid title author description ms.author ms.date ms.assetid msc.legacyurl msc.type
signalr/overview/guide-to-the-api/mapping-users-to-connections Mapping SignalR Users to Connections | Microsoft Docs tfitzmac This topic shows how to retain information about users and their connections. Patrick Fletcher helped write this topic. Software versions used in this topic... aspnetcontent 12/30/2014 f80c08b1-3f1f-432c-980c-c7b6edeb31b1 /signalr/overview/guide-to-the-api/mapping-users-to-connections authoredcontent

Mapping SignalR Users to Connections

by Tom FitzMacken

This topic shows how to retain information about users and their connections.

Patrick Fletcher helped write this topic.

Software versions used in this topic

Previous versions of this topic

For information about earlier versions of SignalR, see SignalR Older Versions.

Questions and comments

Please leave feedback on how you liked this tutorial and what we could improve in the comments at the bottom of the page. If you have questions that are not directly related to the tutorial, you can post them to the ASP.NET SignalR forum or StackOverflow.com.

Introduction

Each client connecting to a hub passes a unique connection id. You can retrieve this value in the Context.ConnectionId property of the hub context. If your application needs to map a user to the connection id and persist that mapping, you can use one of the following:

Each of these implementations is shown in this topic. You use the OnConnected, OnDisconnected, and OnReconnected methods of the Hub class to track the user connection status.

The best approach for your application depends on:

  • The number of web servers hosting your application.
  • Whether you need to get a list of the currently connected users.
  • Whether you need to persist group and user information when the application or server restarts.
  • Whether the latency of calling an external server is an issue.

The following table shows which approach works for these considerations.

More than one server Get list of currently connected users Persist information after restarts Optimal performance
UserID Provider
In-memory
Single-user groups
Permanent, external

IUserID provider

This feature allows users to specify what the userId is based on an IRequest via a new interface IUserIdProvider.

The IUserIdProvider

[!code-csharpMain]

By default, there will be an implementation that uses the user's IPrincipal.Identity.Name as the user name. To change this, register your implementation of IUserIdProvider with the global host when your application starts:

[!code-csharpMain]

From within a hub, you'll be able to send messages to these users via the following API:

Sending a message to a specific user

[!code-csharpMain]

In-memory storage

The following examples show how to retain connection and user information in a dictionary that is stored in memory. The dictionary uses a HashSet to store the connection id. At any time a user could have more than one connection to the SignalR application. For example, a user who is connected through multiple devices or more than one browser tab would have more than one connection id.

If the application shuts down, all of the information is lost, but it will be re-populated as the users re-establish their connections. In-memory storage does not work if your environment includes more than one web server because each server would have a separate collection of connections.

The first example shows a class that manages the mapping of users to connections. The key for the HashSet will be the user's name.

[!code-csharpMain]

The next example shows how to use the connection mapping class from a hub. The instance of the class is stored in a variable name _connections.

[!code-csharpMain]

Single-user groups

You can create a group for each user, and then send a message to that group when you want to reach only that user. The name of each group is the name of the user. If a user has more than one connection, each connection id is added to the user's group.

You should not manually remove the user from the group when the user disconnects. This action is automatically performed by the SignalR framework.

The following example shows how to implement single-user groups.

[!code-csharpMain]

Permanent, external storage

This topic shows how to use either a database or Azure table storage for storing connection information. This approach works when you have multiple web servers because each web server can interact with the same data repository. If your web servers stop working or the application restarts, the OnDisconnected method is not called. Therefore, it is possible that your data repository will have records for connection ids that are no longer valid. To clean up these orphaned records, you may wish to invalidate any connection that was created outside of a timeframe that is relevant to your application. The examples in this section include a value for tracking when the connection was created, but do not show how to clean up old records because you may want to do that as background process.

Database

The following examples show how to retain connection and user information in a database. You can use any data access technology; however, the example below shows how to define models using Entity Framework. These entity models correspond to database tables and fields. Your data structure could vary considerably depending on the requirements of your application.

The first example shows how to define a user entity that can be associated with many connection entities.

[!code-csharpMain]

Then, from the hub, you can track the state of each connection with the code shown below.

[!code-csharpMain]

Azure table storage

The following Azure table storage example is similar to the database example. It does not include all of the information that you would need to get started with Azure Table Storage Service. For information, see How to use Table storage from .NET.

The following example shows a table entity for storing connection information. It partitions the data by user name, and identifies each entity by the connection id, so a user can have multiple connections at any time.

[!code-csharpMain]

In the hub, you track the status of each user's connection.

[!code-csharpMain]