Question: How do I manage anonymous users so that multiple tabs in a single browser are all updated when the Hub sends out a response?
The scenario is as follows:
I would like to integrate SignalR into a project so that anonymous users can live chat with operators. Obviously user's that have authenticated with iIdentity are mapped via the Client.User(username) command. But currently say an anonymous user is browsing site.com/tools and site.com/notTools I can not send messages to all tabs with only a connectionID. Only one tab gathers the response.
I have tried using IWC patch but that tool doesn't account for saving chat information into a database and I think passing variables via ajax isn't a secure way to read/write to a database.
I have also looked in the following: Managing SignalR connections for Anonymous user
However creating a base such as that and using sessions seems less secure than Owin.
I had the idea to use client.user() by creating a false account each time a user connects and delete it when they disconnect. But I would rather not fill my aspnetusers db context with garbage accounts it seems unnecessary.
Is it possible to use UserHandler.ConnectedIds.Add(Context.ConnectionId);
to also map a fake username? Im at a loss.
Would it make sense to use iUserId provider?
public interface IUserIdProvider
{
string GetUserId(IRequest request);
}
Then create a database that stores IP addresses to connectionIDs and single usernames?
database:
Users: With FK to connection IDs
|userid|username|IP |connectionIDs|
| 1 | user1 |127.0.0.1| 1 |
| 2 | user2 |127.0.0.2| 2 |
connectionIDs:
|connectionID|SignalRID|connectionIDs|
| 1 | xx.x.x.x| 1 |
| 2 | xx.xxx.x| 2 |
| 3 | xx.xxxxx| 2 |
| 4 | xxxxx.xx| 2 |
Then Possibly write logic around the connection?
public override Task OnConnected()
{
if(Context.Identity.UserName != null){
//add a connection based on the currently logged in user.
}
else{
///save new user to database?
}
}
but the question still remains how would I handle multiple tabs with that when sending a command on the websocket?
update To be clear, my intent is to create a live chat/support tool that allows for in browser anonymous access at all times.
The client wants something similar to http://www.livechatinc.com
I have already created a javascript plugin that sends and receives from the hub, regardless of what domain it is on. (my client has multisites) the missing piece to the puzzle is the simplest, managing the anonymous users to allow for multi-tabbed conversations.
SignalR provides a simple API for creating server-to-client remote procedure calls (RPC) that call JavaScript functions in client browsers (and other client platforms) from server-side . NET code.
Signals are used for communication (e.g. analog and digital). R stands for real-time. Real-time web refers the ability to have server code push content to the connected clients instantly. Signal R in short refers to Real-time application communication. From Signal R - A Real-Time Application.
SignalR is fast and scalable Like the rest of ASP.NET, SignalR was built for high performance and is one of the fastest real-time frameworks around. Scale out across servers with built-in support for using Redis, SQL Server, or Azure Service Bus to coordinate messages between each instance.
WebSockets is actually the underlying transport that SignalR uses, at least most of the time. SignalR has the ability to fall back to other ways of transporting messages, such as long-polling over HTTP. This is useful in situations where you don't have WebSockets support.
I'm not following the false user account idea (don't know if it works), but will develop an alternative.
The goal could be achieved through a ChatSessionId cookie shared by all browser tabs and creating Groups named as this ChatSessionId.
I took basic chat tutorial from asp.net/signalr and added functionality to allow chat from multiple tabs as the same user.
1) Assign a Chat Session Id in "Chat" action to identify the user, as we don't have user credential:
public ActionResult Chat()
{
ChatSessionHelper.SetChatSessionCookie();
return View();
}
2) Subscribe to chat session when enter the chat page
client side
$.connection.hub.start()
.then(function(){chat.server.joinChatSession();})
.done(function() {
...
server side (hub)
public Task JoinChatSession()
{
//get user SessionId to allow use multiple tabs
var sessionId = ChatSessionHelper.GetChatSessionId();
if (string.IsNullOrEmpty(sessionId)) throw new InvalidOperationException("No chat session id");
return Groups.Add(Context.ConnectionId, sessionId);
}
3) broadcast messages to user's chat session
public void Send(string message)
{
//get user chat session id
var sessionId = ChatSessionHelper.GetChatSessionId();
if (string.IsNullOrEmpty(sessionId)) throw new InvalidOperationException("No chat session id");
//now message will appear in all tabs
Clients.Group(sessionId).addNewMessageToPage(message);
}
Finally, the (simple) ChatSessionHelper class
public static class ChatSessionHelper
{
public static void SetChatSessionCookie()
{
var context = HttpContext.Current;
HttpCookie cookie = context.Request.Cookies.Get("Session") ?? new HttpCookie("Session", GenerateChatSessionId());
context.Response.Cookies.Add(cookie);
}
public static string GetChatSessionId()
{
return HttpContext.Current.Request.Cookies.Get("Session")?.Value;
}
public static string GenerateChatSessionId()
{
return Guid.NewGuid().ToString();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With