Taras Kovalenko Taras Kovalenko - 2 months ago 27
AngularJS Question

SignalR Web API send message to current user

I have web app project and an angular 2 project.
I would like use SignalR to send message from the server.
Then I found this article about implementing it.
But I don't know how to send message to the current user.

Code for send message C#:

public class EventHub : Hub
{
public async Task Subscribe(string channel)
{
await Groups.Add(Context.ConnectionId, channel);

var @event = new ChannelEvent
{
Name = $"{Context.ConnectionId} subscribed",
Data = new
{
Context.ConnectionId,
ChannelName = channel
}
};

await Publish(@event);
}

public async Task Unsubscribe(string channel)
{
await Groups.Remove(Context.ConnectionId, channel);

var @event = new ChannelEvent
{
Name = $"{Context.ConnectionId} unsubscribed",
Data = new
{
Context.ConnectionId,
ChannelName = channel
}
};

await Publish(@event);
}

public Task Publish(ChannelEvent channelEvent)
{
Clients.Caller.OnEvent(Constants.AdminChannel, channelEvent);

return Task.FromResult(0);
}

public override Task OnConnected()
{
var @event = new ChannelEvent
{
Name = $"{Context.ConnectionId} connected",
Data = new
{
Context.ConnectionId,
}
};

Publish(@event);

return base.OnConnected();
}

public override Task OnDisconnected(bool stopCalled)
{
var @event = new ChannelEvent
{
Name = $"{Context.ConnectionId} disconnected",
Data = new
{
Context.ConnectionId,
}
};

Publish(@event);

return base.OnDisconnected(stopCalled);
}
}

public static class Constants
{
public const string AdminChannel = "admin";
public const string TaskChannel = "tasks";
}

public class ChannelEvent
{
public string Name { get; set; }

public string ChannelName { get; set; }

public DateTimeOffset Timestamp { get; set; }

public object Data
{
get { return _data; }
set
{
_data = value;
Json = JsonConvert.SerializeObject(_data);
}
}
private object _data;

public string Json { get; private set; }

public ChannelEvent()
{
Timestamp = DateTimeOffset.Now;
}
}


Then in my controller I create IhubContent

private readonly IHubContext _context = GlobalHost.ConnectionManager.GetHubContext<EventHub>();


and invoke my publish event:

private void PublishEvent(string eventName, StatusModel status)
{
_context.Clients.Group(Constants.TaskChannel).OnEvent(Constants.TaskChannel, new ChannelEvent
{
ChannelName = Constants.TaskChannel,
Name = eventName,
Data = status
});
}


But this message sent to all users. Help me to fix this issue and implement code to the send message to the current user.

Answer

The IHubContext object your are using has multiple methods, one of which is Clients, of type IHubConnectionContext.

In there you have Groups, Group, Clients & Client methods which abstract what you want to target.

In your case using:

_context.Clients.Client(connectionId).send(message);

should be working fine (you still need to propagate the connectionId though).

N.B.: send is a JS method that should be implemented on client-side.