Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR send message to specific client

I have a hub with a static method which broadcasts notifications to all users currently.

public class NotificationHub : Hub
{
    private static string connString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString();

    [HubMethodName("sendNotifications")]
    public static void SendNotifications()
    {
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
        context.Clients.All.updateNotifications();
    }
}

I need to take some text box input from the front end javascript e.g. 10038 which is the userID and send this to a server class e.g.

public class NotificationRepository
{
    private readonly string _connString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;

    public IEnumerable<Notifications> GetNotifications(int userID)
    {
        var notifications = new List<Notifications>();

        using (var connection = new SqlConnection(_connString))
        {
            connection.Open();
            using (var command = new SqlCommand(String.Format(@"SELECT [ID], [UserID], [Message] FROM [dbo].[Notification] WHERE [UserID] = {0}", userID), connection))
            {
                command.Notification = null;

                var dependency = new SqlDependency(command);
                dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);

                if (connection.State == ConnectionState.Closed)
                {
                    connection.Open();
                }

                var reader = command.ExecuteReader();

                while (reader.Read())
                {
                    notifications.Add(item: new Notifications { ID = (int)reader["ID"], UserID = (int)reader["UserID"], Message = (string)reader["Message"] });
                }
            }
        }
        return notifications;
    }

    private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Type == SqlNotificationType.Change)
        {
            NotificationHub.SendNotifications();
        }
    }
}

I return a set of notifications for the specific user as defined by the User ID but I can't seem to figure out how I map the response so that I only return notifications to that specific client in signalR.

How do I go about mapping the connection IDs of the clients to the userID that was entered?

I have read the signalR documentation but it's very vague and other solutions online don't seem to address this specific issue.

Any help would be much appreciated.

EDIT

So far I have tried using IUserIdProvider and this is what I have so far but this does not seem to work.

On the front end I have set my queryString as follows

$.connection.hub.qs = "userId=" + $('#userText').val();

This is my custom IUserIdProvider

public class CustomUserIdProvider : IUserIdProvider
{
    public string GetUserId(IRequest request)
    {
         return request.QueryString["userId"];
     }
 }

This is what my NotificationRepository looks like

public class NotificationRepository
{
    private readonly string _connString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;

    public IEnumerable<Notifications> GetUserNotifications(string userID)
    {
        var notifications = new List<Notifications>();

        using (var connection = new SqlConnection(_connString))
        {
            connection.Open();
            using (var command = new SqlCommand(String.Format(@"SELECT [ID], [UserID], [Message] FROM [dbo].[Notification] WHERE [UserID] = {0}", userID), connection))
            {
                command.Notification = null;

                var dependency = new SqlDependency(command);
                dependency.OnChange += new OnChangeEventHandler((sender, e) => dependency_OnChange(sender, e, userID));

                if (connection.State == ConnectionState.Closed)
                {
                    connection.Open();
                }

                var reader = command.ExecuteReader();

                while (reader.Read())
                {
                    notifications.Add(item: new Notifications { ID = (int)reader["ID"], UserID = (int)reader["UserID"], Message = (string)reader["Message"] });
                }
            }
        }
        return notifications;
    }


    private void dependency_OnChange(object sender, SqlNotificationEventArgs e, string userID)
    {
        if (e.Type == SqlNotificationType.Change)
        {
            NotificationHub.SendNotifications(userID);
        }
    }
}

And this is my hub

public class NotificationHub : Hub
{
    private static string connString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString();

    [HubMethodName("sendNotifications")]
    public static void SendNotifications(string userId)
    {
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
        context.Clients.Client(userId).updateNotifications();
    }
}
like image 574
Ballamory Avatar asked May 22 '16 17:05

Ballamory


1 Answers

So I've figured out what the issue is in this scenario. When initialising the queryString

$.connection.hub.qs = "userId=" + $('#userText').val();

You must do this before you start the connection to the hub.

like image 107
Ballamory Avatar answered Oct 10 '22 07:10

Ballamory