new net hubconnectionbuilder asp asp.net notifications signalr signalr-hub

asp.net - net - signalr groups



AsignaciĆ³n de conexiones SignalR a los usuarios (4)

Considere una aplicación web como Facebook, que puede enviar notificaciones en tiempo real a los usuarios.

¿Cuál es la mejor manera, utilizando asp.net SignalR , para realizar un seguimiento de qué identificadores de conexión pertenecen a qué usuario, incluso si el usuario se desconecta o se vuelve a conectar más tarde?


Echa un vistazo a la siguiente publicación de blog:

Asignación de conexiones SignalR de ASP.NET a usuarios de aplicaciones reales

En resumen, OnConnected los OnConnected conexión al usuario en el método OnConnected y eliminará esa conexión en el método OnDisconnected . Tenga en cuenta que un usuario de la aplicación puede tener múltiples conexiones. Por lo tanto, debe tener una relación de uno a varios entre su usuario y los ID de conexión. La publicación vinculada anterior lo explica en detalle con una muestra.


Hice esto para una aplicación interna. La forma en que lo hice es que cuando un usuario se conecta, el servidor le pide al usuario que se registre. De esta forma sé que no solo un usuario está conectado y su signalR connnectionID, sino que también pueden decirme cualquier otra información (como nombre de usuario o lo que sea).

Cuando se vuelvan a conectar, les pido que lo vuelvan a hacer.

SignalR mantendrá el mismo ID de conexión por cliente, incluso si vuelven a conectar lo que es bueno. Una reconexión no es lo mismo que una conexión inicial. Las nuevas conexiones indican un nuevo cliente, pero una reconexión está en el mismo cliente.

En mi aplicación, mantuve un diccionario independiente de threadsafe que hacía un seguimiento de qué usuario y qué connectionID estaba haciendo qué. De esta forma puedo decir "ah, enviar un mensaje al usuario ABC" y buscar su ID de conexión. Luego actúe sobre el objeto de los clientes del Hub en la señal R para ese ID de conexión. Si lo haces de esta manera, incluso puedes tener el mismo "usuario" en múltiples conexiones. Imagine que el usuario "abc" está abierto en dos pestañas del navegador. Si fue estrictamente por connectionID, técnicamente serían dos usuarios diferentes. Sin embargo, al mantener algún tipo de agrupación de recopilación local de usuarios y conexiones, ahora puede tener múltiples conexiones para el mismo usuario.

Debo mencionar que si lo hace de esta manera, debe asegurarse de que su sitio maneje lo que sucede cuando se reinicia y pierde toda la información de conexión. Para mí, cuando alguien se vuelve a conectar les pido que vuelvan a identificarse. De esta forma, puedo reconstruir mi diccionario local cuando el servidor se conecta sin preocupaciones. Tiene más sobrecarga porque ahora le está pidiendo a todos sus clientes que le envíen información, pero dependiendo de su caso de usuario, esto podría escalonarse o agruparse o distribuirse de otro modo para ayudarlo a manejar la carga.

En general, como quiera que obtenga información local (ya sea pidiéndole al usuario que la suministre), o mediante la información de la sesión de contexto HTTP, necesita rastrearla usted mismo.


Bueno, utilicé un enfoque diferente, extendí la clase ApplicationUser así:

// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more. public class ApplicationUser : IdentityUser { //public int ApplicationUserId { get; set; } //public string Name { get; set; } //public string Address { get; set; } //public string City { get; set; } //public string State { get; set; } //public string Zip { get; set; } [Required] public string Email { get; set; } [Required] public override string UserName { get; set; } [NotMapped] public string ConnectionId { get; set; } [NotMapped] public string ChattingUserConnectionId { get; set; } //public string HomeTown { get; set; } //public DateTime? BirthDate { get; set; } }

Y en mi centro, estoy haciendo algo como eso:

public class ChatHub : Hub { #region Data Members private static ApplicationDbContext applicationDbContext = new ApplicationDbContext(); private static UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(applicationDbContext)); private static List<ApplicationUser> connectedUsers = new List<ApplicationUser>();

Y cuando un usuario se conecta al chat, obtengo su objeto ApplicationUser por su nombre de usuario y lo agrego a la lista connectedUsers. Cuando él se desconecta, lo remuevo.

Me encontré con algunas excepciones aleatorias con estados de EF, que me hicieron crear ApplicationDbContext y UserManager cada vez que se accedía en lugar de configurarlo en un objeto estático:

private ApplicationUser GetCurrentUser() { ApplicationDbContext applicationDbContext = new ApplicationDbContext(); UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(applicationDbContext)); var userName = Context.User.Identity.GetUserName(); var user = userManager.FindByName<ApplicationUser>(userName); return user; }

Editar:

El código del concentrador tiene algunos problemas para cargar objetos secundarios del usuario. Este código que también se usa en la plantilla asp.net funcionará mejor, ApplicationDBContext no es necesario:

private ApplicationUserManager _userManager { get { return HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); } } var user = _userManager.FindByName<ApplicationUser, string>(userName);


Hay un artículo muy bueno en la sección del tutorial SignalR de ASP.NET. He incluido el párrafo introductorio a continuación.

Asignación de usuarios de SignalR a las conexiones

Cada cliente que se conecta a un concentrador pasa una identificación de conexión única. Puede recuperar este valor en la propiedad Context.ConnectionId del contexto del concentrador. Si su aplicación necesita asignar un usuario a la identificación de conexión y persistir esa asignación, puede usar una de las siguientes opciones:

  • El proveedor de identificación de usuario (SignalR 2)
  • Almacenamiento en memoria, como un diccionario
  • Grupo SignalR para cada usuario

Almacenamiento externo permanente, como una tabla de base de datos o almacenamiento de tablas Azure. Cada una de estas implementaciones se muestra en este tema. Utiliza los métodos OnConnected, OnDisconnected y OnReconnected de la clase Hub para rastrear el estado de conexión del usuario.


Proveedor de usuario

Si usa el proveedor de membresía estándar de ASP.NET ( IPrincipal.Identity.Name ), puede hacer lo siguiente para acceder a un cliente en función de una cuenta de usuario. Si tiene su propio sistema de usuario, puede crear su propio proveedor.

public class MyHub : Hub { public void Send(string userId, string message) { Clients.User(userId).send(message); } }