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

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" });

Related

SignalR Hub is not connecting from Client, even not showing any error

Included Scripts version 2.2.3 based on a version of signalR packages.
<script src="Scripts/jquery.signalR-2.2.3.min.js"></script>
<script src="Scripts/jquery.signalR-2.2.3.js"></script>
<script src="~/signalr/hubs"></script>
Hub Connection from Client side by script in HTML page, the code mentioned below
var chatProxy = $.connection.schoolAppHub;
$.connection.hub.start().done(function ()
{
$('#btnSend').click(function ()
{
chatProxy.server.broadCastMessage($("#spnName").text(), $("#txtMsg").val());
$('#txtMsg').val('').focus();
})
})
Hub class code is also noted below
public class SchoolAppHub : Hub
{
public void BroadCastMessage(String msgFrom, String msg)
{
Clients.All.receiveMessage(msgFrom, msg);
}
}

SignalR save sender Id and receiver Id in ASP.NET MVC C#

I am following this Signal R tutorial from Microsoft. I have already configured everything for SignalR to be working and it does work.
This is my Front End script to call SignalR
<script>
$(function () {
// Reference the auto-generated proxy for the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call back to display messages.
chat.client.addNewMessageToPage = function (name, message) {
// Add the message to the page.
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</li>');
};
// Get the user name and store it to prepend to messages.
$('#displayname').val(prompt('Enter your name:', ''));
// Set initial focus to message input box.
$('#message').focus();
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
// This optional function html-encodes messages for display in the page.
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
As you can see in the microsoft tutorial, I require to create a hub class with this method.
public void Send(string name, string message)
{
// Call the addNewMessageToPage method to update clients.
Clients.All.addNewMessageToPage(name, message);
}
My question is, given an mvc application with login (each user have its own Id), how can I send the receiver Id to my backend so I can save it into my database?
I have already tried to modify the Send function
public class chat
{
public int Id { get; set; }
public string Message { get; set; }
public string Name { get; set; }
public Guid receiverId { get; set; }
}
public void Send(string name, string message,string receiverId)
{
// Call the addNewMessageToPage method to update clients.
chatultimo chat = new chatultimo();
chat.Name = name;
chat.Message = message;
chat.Id = Guid.NewGuid();
_dbContext.chatultimo.Add(chat);
_dbContext.SaveChanges();
Clients.All.addNewMessageToPage(name, message);
}
I also made a modification in my function in the front end
chat.client.addNewMessageToPage = function (name, message)
you can see that the Send function is being called in the front end, but after modifying the send function my application is not hiting the backend.
chat.client.addNewMessageToPage = function (name, message,receiverId)
Another thing is I do not think it is a good idea to modify the send function. I think it is much better to do the database job in the $.connection.hub.start().done(function () ...
to make sure it is only executed after the handshake.

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.

Private chat with SignalR - talk to strangers

I would like to write a simple chat on the principle as omegle.com. I wrote that if the user enters the server and the queue is empty creates a new group and falls to the queue. When the other person enters, it connects with this in the queue.
Here's my code:
public class UserGroup
{
public string GroupName { get; set; }
}
public class ChatHub : Hub
{
public static Queue<UserGroup> Users = new Queue<UserGroup>();
public static string Group { get; set; }
public Task JoinGroup(string groupName)
{
return Groups.Add(Context.ConnectionId, groupName);
}
public override System.Threading.Tasks.Task OnConnected()
{
if(Users.Count == 0)
{
var user = new UserGroup { GroupName = Context.ConnectionId };
Users.Enqueue(user);
Group = user.GroupName;
JoinGroup(user.GroupName);
}
else
{
JoinGroup(Users.Peek().GroupName);
Group = Users.Peek().GroupName;
Users.Dequeue();
}
return base.OnConnected();
}
public void SayHello(string name, string helloMsg)
{
Clients.Caller.Hello(name, helloMsg);
}
public void Send(string msg)
{
Clients.Group(Group).SendMessage(msg);
}
}
Unfortunately, when I connect to someone else, everything breaks down and does not create a new group for new people. All static data, but unfortunately not SignalR allows otherwise. You have an idea how to get around this?
I don't think you need a Queue or use groups in this scenario. The easiest solution would be to send the stranger's client id to the other client. You should incorporate locking because you access shared state from different hub instances:
Create a new ASP.NET Web Application project and select MVC as framework.
Add Microsoft.AspNet.SignalR and knockoutjs nuget packages and update all packages.
The current SignalR version requires that you add a Startup class:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
Add a hub class:
public class ChatHub : Hub
{
private static string waitingUser;
private static readonly object SyncLock = new object();
public void SendMessage(string text, string clientId)
{
this.Clients.Client(clientId).addMessage(text);
}
public override Task OnConnected()
{
var newUser = this.Context.ConnectionId;
string otherUser;
lock (SyncLock)
{
if (waitingUser == null)
{
waitingUser = newUser;
return base.OnConnected();
}
otherUser = waitingUser;
waitingUser = null;
}
this.Clients.Caller.startChat(otherUser);
this.Clients.Client(otherUser).startChat(newUser);
return base.OnConnected();
}
}
Finally, add the following code to your view:
#{
ViewBag.Title = "Chat wit a Stranger";
}
<h1>Chat with a Stranger</h1>
<div data-bind="foreach: messages">
<div data-bind="text: $data"></div>
</div>
<hr/>
<form data-bind="submit: send, visible: connected">
<input type="text" data-bind="value: text" />
<button type="submit">Send</button>
</form>
<script src="~/Scripts/knockout-3.2.0.debug.js"></script>
<script src="~/Scripts/jquery-2.1.1.js"></script>
<script src="~/Scripts/jquery.signalR-2.1.2.js"></script>
<script src="~/signalr/hubs"></script>
<script>
var hub = $.connection.chatHub;
var vm = {
otherUser: "",
messages: ko.observableArray(["Waiting for a stranger..."]),
connected: ko.observable(false),
text: ko.observable(""),
send: function () {
var text = vm.text();
if (text.length == 0) return;
hub.server.sendMessage(text, vm.otherUser);
vm.messages.push("You: " + text);
vm.text("");
},
addMessage: function(text) {
vm.messages.push("Stranger: " + text);
},
startChat: function (otherUser) {
vm.otherUser = otherUser;
vm.messages(["A stranger has connected. Say hello!"]);
vm.connected(true);
}
}
ko.applyBindings(vm);
hub.client.startChat = vm.startChat;
hub.client.addMessage = vm.addMessage;
$.connection.hub.start();
</script>

How to call signalr client method from different server

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

Categories