How to call signalr client method from different server - c#

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

Related

SignalR messages not received in client when called via Azure WebRole Run() function

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.

Call signalr from another controller

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();

SignalR message not being received on the client

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(){ }

SignalR .Net client: How do I send a message to a Group?

I am using the sample Chat application from the SignalR Wiki Getting Started Hubs page. I have extended it to add Group support and it is working fine.
However, now I want to send a message to the group from an external Console application. Here is my code for the Console app and below that my code for Groups. How do I send a message to a Group from a proxy? Is it possible?
// Console App
using System;
using Microsoft.AspNet.SignalR.Client.Hubs;
namespace SignalrNetClient
{
class Program
{
static void Main(string[] args)
{
// Connect to the service
var connection = new HubConnection("http://localhost:50116");
var chatHub = connection.CreateHubProxy("Chat");
// Print the message when it comes in
connection.Received += data => Console.WriteLine(data);
// Start the connection
connection.Start().Wait();
chatHub.Invoke("Send", "Hey there!");
string line = null;
while ((line = Console.ReadLine()) != null)
{
// Send a message to the server
connection.Send(line).Wait();
}
}
}
}
SignalR Web App Host:
namespace SignalrServer.Hubs
{
public class Chat : Hub
{
public void Send(string message)
{
// Call the addMessage method on all clients
Clients.All.addMessage(message);
Clients.Group("RoomA").addMessage("Group Message " + message);
}
//server
public void Join(string groupName)
{
Groups.Add(Context.ConnectionId, groupName);
}
}
}
Default.aspx
<script src="http://code.jquery.com/jquery-1.8.2.min.js" type="text/javascript"></script>
<script src="Scripts/jquery.signalR-1.0.1.min.js" type="text/javascript"></script>
<!-- If this is an MVC project then use the following -->
<!-- <script src="~/signalr/hubs" type="text/javascript"></script> -->
<script src="signalr/hubs" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
// Proxy created on the fly
var chat = $.connection.chat;
// Declare a function on the chat hub so the server can invoke it
chat.client.addMessage = function (message) {
$('#messages').append('<li>' + message + '</li>');
};
$.connection.hub.start(function () {
chat.server.join("RoomA");
});
// Start the connection
$.connection.hub.start().done(function () {
$("#broadcast").click(function () {
// Call the chat method on the server
chat.server.send($('#msg').val());
});
});
});
</script>
<div>
<input type="text" id="msg" />
<input type="button" id="broadcast" value="broadcast" />
<ul id="messages">
</ul>
</div>
What I have done with something similar is to create a method which accepts an object of your choice, e.g.
Your new class
public class MyMessage{
public string Msg { get; set; }
public string Group { get; set; }
}
Then create a method in the Hub that accepts this object.
public void Send(MyMessage message)
{
// Call the addMessage method on all clients
Clients.All.addMessage(message.Msg);
Clients.Group(message.Group).addMessage("Group Message " + message.Msg);
}
Then from your client, you can then pass this object in.
chatHub.Invoke<MyMessage>("send", new MyMessage() { Msg = "Hello World", Group = "RoomA" });
You can then also call this from the JS client
chat.server.send({ Msg: "Hello World", Group: "RoomA" });

Accidently Sending Multiple Messages with SignalR

I'm new to SignalR but I understand the concept.
My goal is to expose web services which when called will update all connected clients. I've built a little knockout js to connect to the hub and that works well. When I click my start button it sends a message to each of the clients connected like it is supposed to. Here is the code for a background.
Hub:
[HubName("realTimeData")]
public class RealTimeDataHub : Hub
{
public void UpdateFlash(string message)
{
Clients.flashUpdated(message);
}
public void clear()
{
Clients.cleared();
}
}
JS:
function viewModel(){
var self = this;
self.messages = ko.observableArray([]);
self.hub = $.connection.realTimeData;
self.hub.flashUpdated = function (m) {
self.messages.push(new message(m));
};
self.hub.cleared = function () {
self.messages.removeAll();
};
self.Start = function () {
self.hub.updateFlash("Updated Flashed from client");
};
self.Stop = function () {
self.hub.clear();
};
$.connection.hub.start();
}
ko.applyBindings(new viewModel());
MVC API:
public class HomeController : Controller
{
public ActionResult Update()
{
GetClients().updateFlash("From server");
return Json(new { result = "ok" }, JsonRequestBehavior.AllowGet);
}
private static dynamic GetClients()
{
return GlobalHost.ConnectionManager.GetHubContext<RealTimeData.Hubs.RealTimeDataHub>().Clients;
}
}
The problem:
When I call the "Update" method from my controller (Home/Update, not a real API yet) it sends one signal for each of the clients connected. So if I have 2 clients connected, I will get 2 "From Server" messages to each client and so on. I would only like the one...
Any suggestions? Anything is appreciated
Thanks,
Matt
Solution:
Must import 'using SignalR.Client;'
public ActionResult Update()
{
hub.Invoke("UpdateFlash", "From the Home Controller");
//GetClients().updateFlash("From server");
return Json(new { result = "ok" }, JsonRequestBehavior.AllowGet);
}
Here is where I found the solution:
https://github.com/SignalR/SignalR/wiki/SignalR-Client-Hubs
I hope this can help somebody out.
Matt

Categories