I have a ChatHub sending message to the client:
public class ChatHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addNewMessageToPage(name, message);
}
}
How can I call the Send function to broadcast the message to all client from another controller?
I have tried this:
[HttpPost]
public void Post(Chat chat)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
hubContext.Clients.All.Send(chat.Name, chat.Message);
}
You need to call addNewMessageToPage in your Post action method.
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
hubContext.Clients.All.addNewMessageToPage(chat.Name, chat.Message);
Then in your JS file:
var chatHub = $.connection.chatHub;
chatHub.client.addNewMessageToPage= function (name, message) {
//Add name and message to the page here
};
$.connection.hub.start();
Related
SignalR core is very new, so the docs detail how to use about it are very rare.
I've done the tutorial from Microsoft and successfully sent messages to all the clients. Now I want to send for specific user, with
public Task SendPrivateMessage(string user, string message, string to)
{
return Clients.User(to).SendAsync("ReceiveMessage", user, message);
}
the "to" value is the ConnectionID I got from the
public override Task OnConnectedAsync()
{
Console.WriteLine("New ID Connected: " + Context.ConnectionId);
return base.OnConnectedAsync();
}
Here is my client:
public async void InitSignalRAsync()
{
ChatMessage mess = new ChatMessage();
hubConnection = new HubConnectionBuilder().WithUrl("http://localhost:5000/chatHub").Build();
await hubConnection.StartAsync();
hubConnection.On<string, string>("ReceiveMessage", async (user, message) =>
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
mess.user = user;
mess.message = message;
Messages.Add(mess);
});
});
}
private void Send_Click(object sender, RoutedEventArgs e)
{
hubConnection.InvokeAsync("SendPrivateMessage", User.Text, Text.Text, To.Text);
}
The console logs nothing error so I guess it did send but why can't I receive it?
For send to client by client's connectionId you should use of Clients.Client(coonectionId)
,Clients.User() is for send to uniqe user by user's Id.to do send message by user id you can try as follows:
-create a CustomUserIdProvider:
public class CustomUserIdProvider: IUserIdProvider
{
public virtual string GetUserId(HubConnectionContext connection)
{
//get current user id by httpcontext
}
}
and then in startup.cs:
services.AddSignalR();
services.AddSignalRCore();
services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
now in your hub you can send message by user id:
public void Send(string userId, string message)
{
Clients.User(userId).send(message);
}
for more info go to this link
I'm trying to send a message via SignalR from my WebRole to the client but it's not appearing. It appears fine when I test call it from a Controller, but when called from the Run() function, it doesn't seem to make it over to the client.
public override void Run()
{
processingQueueClient.OnMessage((message) =>
{
message.Complete();
MainHub.Send("Test 1");
});
completedEvent.WaitOne();
}
namespace MainWebRole
{
public class MainHub : Hub
{
public static void Send(string message)
{
var context = GlobalHost.ConnectionManager.GetHubContext<MainHub>();
context.Clients.All.broadcastMessage(message);
}
}
}
<script>
$(function () {
var chat = $.connection.mainHub;
chat.client.broadcastMessage = function (message) {
var notificationText = "<div><button type=\"button\" class=\"btn btn-default\" onclick=\"onClickClearComplete()\">Clear Complete</button></div><div class=\"spacer10\"></div><div><table class=\"table table-bordered\">";
notificationText += "<tr><td nowrap><span><i class=\"fa fa-pause\"></i> Pending \"" + message + "\"</span></td></tr>";
notificationText += "</table></div>";
$("#statusText").html(notificationText);
};
$.connection.hub.start().done(function () {
});
});
</script>
Please try to run your signalR send function via below steps:
1) Install-Package Microsoft.AspNet.SignalR.Client
2) write below code in Azure web role in run function.
HubConnection _hub = new HubConnection("http://localhost:1942");
var _proxy = _hub.CreateHubProxy("MainHub");
if (_hub.State == ConnectionState.Disconnected)
{
await _hub.Start();
}
await _proxy.Invoke("Send", "jambor");
http://localhost:1942 is your SignalR server site.
MainHub is your SignalR hub class name
Send is your function in MainHub class.
I am trying to pass a custom object from self hosted signalr hub server to all the clients, the method in client side not getting invoked .But if the same custom class object is passed from client to server works fine, meaning it invokes the server method.
below is the sample code :
public class ChatHub : Hub
{
public void Send(DataContract message)
{
//below call not reaching to client while passing custom obj
Clients.All.SendMessage(message);
//below string passing works - means invokes client method
Clients.All.SendMsg("test");
}
}
custom class defined in both client and server project via dll:
public class DataContract
{
public string Name
{
get;set;
}
public int Id
{
get;set;
}
}
client side method:
public class SignalRClient
{
HubConnection hubConnection = null;
IHubProxy chat;
public SignalRClient()
{
hubConnection = new HubConnection("https://localhost/");
chat = hubConnection.CreateHubProxy("ChatHub");
}
public void StartConnection()
{
if (hubConnection != null)
{
hubConnection.Start().Wait();
}
chat.On<DataContract>("SendMessage", (stock) =>
{
Console.WriteLine("name {0} id {1}", stock.Name, stock.Id.ToString());
});
chat.On<string>("SendMsg", (message) =>
{
Console.WriteLine(message);
});
}
public void SendMessage(DataContract dd)
{
dd.Name = "test";
chat.Invoke("Send", dd).Wait();
}
public void SendMessage(string msg)
{
chat.Invoke("SendMsg", "Console app", msg).Wait();
}
}
//program.cs
main()
{
SignalRClient client = new SignalRClient();
client.StartConnection();
string msg = null;
while ((msg = Console.ReadLine()) != null)
{
DataContract dd = new DataContract { Name = "arun", Id = 9 };
//below calls reaches to server both string type and custome obj
client.SendMessage(dd);
client.SendMessage("client");
}
}
Any clue on why when calling from server (i.e Clients.All.SendMessage(message); ) not invoking client method when param is custom object.
Thanks in advance.
I have javascript client code:
<script>
$(function () {
var chat = $.connection.notificationHub;
chat.client.newMessage = function (message) {
alert(message);
// Add the message to the page.
$('#messages').append('<li><strong>' + message + '</strong>: </li>');
};
$.connection.hub.start().done();
});
</script>
My hub class in an dll name -- signalcomponent
public class NotificationHub : Hub
{
public async Task SendAll(string message)
{
await Clients.All.newMessage(message);
}
}
my signalrcomponent is now used in another website(backend) from where i want to send message to another website, but using the same hub.
In backend website, i use signalrcomponent dll and samehub
now i try to call the "newMessage" method of other website/client
using following code:
public class NotificationBroadcaster
{
private IHubContext _hubContext;
public NotificationBroadcaster()
{
_hubContext = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
}
public async Task SendAll(string message)
{
await _hubContext.Clients.All.newMessage(message);
}
}
But this is not working
help please
I've been trying to get my WPF client app to receive a SignalR message sent by the WCF service. I've tried many things and have now resorted to hacking away in the hopes that something just works. I've followed tutorials and examples online, and I simply can't get my WPF OnSignalRMessage() method to get called. Where am I going wrong here?
My hub:
public class PrestoHub : Hub
{
public void Send(string message)
{
Clients.All.OnSignalRMessage(message);
}
}
My startup class:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HubConfiguration { EnableCrossDomain = true };
app.MapHubs("http://localhost:8084", config);
}
}
The method that starts my SignalR host (within my WCF service host):
private void StartSignalRHost()
{
const string url = "http://localhost:8084";
WebApplication.Start<Startup>(url);
}
The code to actually send some message:
GlobalHost.ConnectionManager.GetHubContext<PrestoHub>().Clients.All.OnSignalRMessage("snuh");
Console.WriteLine("Sent 'snuh' to all clients...");
My WPF client methods:
private void InitializeSignalR()
{
var hubConnection = new Connection("http://localhost:8084");
hubConnection.Start();
hubConnection.Received += OnSignalRMessage;
}
private void OnSignalRMessage(string data)
{
MessageBox.Show(data);
}
While I'm still struggling to understand the how and why, I was able to get it working. +1 to N. Taylor Mullen for pointing me in the right direction. In addition to his suggestion on the client side, I had to change some server code as well, namely using an empty hub and a simplified Startup class.
My hub:
public class PrestoHub : Hub{}
Note: The hub is empty because we're not calling methods within it. As we'll see later, we get the hub context and send messages to the clients.
My startup class:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapHubs();
}
}
The above code seems to be what fixed the problem. This also works:
var config = new HubConfiguration { EnableCrossDomain = true };
app.MapHubs(config);
But as soon as I specify a URL, my client doesn't receive the messages (tried with and without the "SignalR" part):
app.MapHubs("http://localhost:8084/SignalR", config);
The method that starts my SignalR host (within my WCF service host):
private void StartSignalRHost()
{
const string url = "http://localhost:8084";
WebApplication.Start<Startup>(url);
}
The code to actually send some message:
var hubContext = GlobalHost.ConnectionManager.GetHubContext<PrestoHub>();
hubContext.Clients.All.OnSignalRMessage("snuh");
My WPF client method:
private void InitializeSignalR()
{
var hubConnection = new HubConnection("http://localhost:8084");
var prestoHubProxy = hubConnection.CreateHubProxy("PrestoHub");
prestoHubProxy.On<string>("OnSignalRMessage", (data) =>
{
MessageBox.Show(data);
});
hubConnection.Start();
}
You're creating a PersistentConnection not a hub connection. In order to get messages from your PrestoHub you first need to connect with a HubConnection and then you need to handle the event "OnSignalRMessage".
So your client code would now look like:
private void InitializeSignalR()
{
var hubConnection = new HubConnection("http://localhost:8084");
var prestoHubProxy = hubConnection.CreateHubProxy("PrestoHub");
// Bind the "OnSignalRMessage" to a function
prestoHubProxy.On<string>("OnSignalRMessage", (data) => {
MessageBox.Show(data);
});
hubConnection.Start();
}
If your methods on the server side are asynchronous make sure they return a task instead of void. That is you should have
public async Task Method(){ }
and not
public async void Method(){ }