Differentiating between multiple clients when multiple services are running in SignalR - javascript

I have a Windows Service written in C# that uses SignalR to self-host for each respective client. This windows service will receive some parameters from a C# MVC Web Application that will be retrieved via the Send() method in the MyHub class. I'm parsing out the message variable and doing things with it. So it looks something like this:
MyCustomService.cs
public partial class MyCustomService: ServiceBase
{
private IDisposable SignalR;
public MyCustomService()
{
InitializeComponent();
eventLog1 = new EventLog();
if (!EventLog.SourceExists("MySource"))
{
EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLog1.Source = "MySource";
eventLog1.Log = "MyNewLog";
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("Service started.");
string url = "http://localhost:8080";
SignalR = WebApp.Start(url);
eventLog1.WriteEntry("Server running on " + url);
}
protected override void OnStop()
{
eventLog1.WriteEntry(LogMessage.Message);
eventLog1.WriteEntry("Service stopped");
SignalR.Dispose();
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
public class MyHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);
// Do other stuff that is omitted for brevity
}
}
My web application running will send data from the server side to the client's local PC via the windows service shown above - when a user presses the Send button.
MyWebApp.html
<!DOCTYPE html>
<html>
<head>
<title>SignalR Simple Chat</title>
<style type="text/css">
.container {
background-color: #99CCFF;
border: thick solid #808080;
padding: 20px;
margin: 20px;
}
</style>
</head>
<body>
<div class="container">
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<ul id="discussion"></ul>
</div>
<!--Script references. -->
<!--Reference the jQuery library. -->
<script src="Scripts/jquery-1.6.4.min.js"></script>
<!--Reference the SignalR library. -->
<script src="Scripts/jquery.signalR-2.2.2.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="http://localhost:8080/signalr/hubs"></script>
<!--Add script to update the page and send messages.-->
<script type="text/javascript">
$(function () {
debugger;
//Set the hubs URL for the connection
$.connection.hub.url = "http://localhost:8080/signalr";
// Declare a proxy to reference the hub.
var chat = $.connection.myHub;
// Create a function that the hub can call to broadcast messages.
chat.client.addMessage = function (name, message) {
// Html encode display name and message.
var encodedName = $('<div />').text(name).html();
var encodedMsg = $('<div />').text(message).html();
// Add the message to the page.
$('#discussion').append('<li><strong>' + encodedName
+ '</strong>: ' + encodedMsg + '</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();
});
});
});
</script>
</body>
</html>
What will happen is that MyCustomService will eventually be installed on multiple computers that are connected to the same network. So:
Computer A has a instance of MyCustomService running on http://localhost:8080
Computer B has a instance of MyCustomService running on http://localhost:8080
Computer C has a instance of MyCustomService running on http://localhost:8080
The problem is this:
How can I differentiate between clients? Will the multiple instances of MyCustomService conflict since they are all on the same network?
For example: If Computer A clicks the Send button, I don't want Computer B to do anything with that data but since Computer B's service is looking at http://localhost:8080 it will receive that information and will also have its own instance of it even know technically they will all be the same.
I want to be able to say:
Computer A has pressed Send then do stuff in the windows service running on Computer A
Tell the duplicate service running in Computer C "dont do anything your Computer C not Computer A!"
Tell the duplicate service running in Computer B "dont do anything your Computer B not Computer A!"

Related

JavaScript connection not starting and function not executing on a JQuery and SignalR web form application

I have a ASP.NET chat application. Using JavaScript, Jquery and Signalr. However my connection does not start to post the message. The browser does prompt me to enter my alias however when l write my message. It does not post it. This is a snippet of the error
C# class :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace Synergince
{
[HubName("chatHub")]
public class ChatHub : Hub
{
public void Send(string name, string message)
{
Clients.All.broadcastMessage(name, message);
}
}
}
JavaScript code :
<div class="container">
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden"id="displayname" />
<ul id="discussion">
</ul>
</div>
//Script references
<script type="text/javascript" src="Scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript" src="Scripts/jquery.signalR-1.2.1.js">
</script>
<script src='<%: ResolveClientUrl("~/signalr/hubs") %>'></script>
<script type="text/javascript">
$(document).ready(function () {
//declare a proxy to reference the hub
var chat = $.connection.chatHub;
//function for the hub to call to broadcast messages
chat.client.broadcastMessage = function (name, message) {
$('#discussion').append('<li><strong>' + name + '</strong>: ' + message + '</li>');
};
//Get the user name and store it to prepend to messages
$('#displayname').val(prompt('Enter preferred alias:', ''));
//initial focus on textbox
$('#message').focus();
//connection start
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
var Name = $('<div />').text($('#displayname').val()).html();
var Msg = $('<div />').text($('#message').val()).html();
//call send method to hub
chat.server.send(Name, Msg);
//clear textbox and set for next input
$('#message').val('').focus();
});
});
});
</script>
</form>
Browser debugger error is:
Uncaught TypeError: $.Deferred is not a function
To this line :
$.connection.hub.start().done(function () {
Not sure what you are trying to achieve with the two VARs below.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
var Name = $('<div />').text($('#displayname').val()).html();
var Msg = $('<div />').text($('#message').val()).html();
//call send method to hub
chat.server.send(Name, Msg);
//clear textbox and set for next input
$('#message').val('').focus();
});
I can only assume you want to send the value of the input boxes. Essentially the same as the sample Chat on the SignalR site.
Change your function to get the "val" of the input:
$.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();
});
});

Cannot read property 'counterHub' of undefined

I am trying to make a simple user counter with SignalR, but for unknown reasons to me I am getting this error in the console. I am very new to signalR and asp.net, but what I have make sense to me, and I don't know why am I getting the error. Can somebody please help me solve this and possibly explain why it is happening?
Here is the code in the Index view.
<div class="row">
Number of online users <strong id="counter"></strong>
<script src="#Url.Content("~/Scripts/jquery-3.1.1.min.js")"></script>
<script src="#Url.Content("~/Scripts/jquery.signalR-2.2.1.min.js")"></script>
<script src="#Url.Content("~/signalr/hubs")"></script>
<script>
$(function () {
var counterHub = $.connection.counterHub;
$.connection.hub.start().done(function () {
});
counterHub.client.UpdateCount = function (count) {
$("#counter").text(count);
}
});
</script>
The hub class :
public class CounterHub : Hub
{
static long counter = 0;
public override System.Threading.Tasks.Task OnConnected()
{
counter = counter + 1;
Clients.All.UpdateCount(counter);
return base.OnConnected();
}
public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
{
counter = counter - 1;
Clients.All.UpdateCount(counter);
return base.OnDisconnected(stopCalled);
}
//public void Hello()
//{
// Clients.All.hello();
//}
}
And the Startup.cs :
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
ConfigureAuth(app);
}
}
Not sure why, but this made it work for me finally. I just surrounded the script tags with #section scripts :
#section scripts{
<script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
$(function () {
var myHub = $.connection.counterHub;
$.connection.hub.start().done(function () {
});
myHub.client.UpdateCount = function (count) {
$("#counter").text(count);
}
});
</script>
}
Is your chat files in the root of application?
The only thing that I think is your page has not connected to Hub proxy javascript file:
ASP.NET SignalR JavaScript Library v1.0.0
This file has some methods to connect to hub, consists:
$.hubConnection.prototype.createHubProxies = function () {
var proxies = {};
this.starting(function () {
// Register the hub proxies as subscribed
// (instance, shouldSubscribe)
registerHubProxies(proxies, true);
this._registerSubscribedHubs(); .......
That lack of this method caused your error:
Cannot read property 'counterHub' of undefined
Because it can not connect to hob and create objec named counterHub.
So please test this: After loading your application in another tab of your browser test this url:
Your-App-Url/signalr/hubs
That in local host is some thing like this:
http://localhost:53398/signalr/hubs
And see if you get the javascript file or not. If not I suggest you to start another project(If it is test).

SignalR chat not connecting to the Hub?

I am trying to create a signalr chatroom in asp.net I am getting the following error "Uncaught TypeError: Cannot read property 'chatHub' of undefined" and the prompt does not come up.
I followed this tutorial https://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr with a modification to the startup class.
Startup.cs..
using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartupAttribute(typeof(MyTrainer.Startup))]
namespace MyTrainer
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var config = new HubConfiguration();
config.EnableDetailedErrors = true;
config.EnableJavaScriptProxies = true;
app.MapSignalR("/signalr", config);
}
}
}
My View (ChatRoom.cshtml)...
#{
ViewBag.Title = "ChatRoom";
}
<!DOCTYPE html>
<html>
<head>
<title>SignalR Simple Chat</title>
<style type="text/css">
.container {
background-color: #99CCFF;
border: thick solid #808080;
padding: 20px;
margin: 20px;
}
</style>
</head>
<body>
<div class="container">
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<ul id="discussion"></ul>
</div>
<!--Script references. -->
<!--Reference the jQuery library. -->
<script src="../Scripts/jquery-1.11.3.min.js"></script>
<!--Reference the SignalR library. -->
<script src="../Scripts/jquery.signalR-2.2.1.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="../signalr/hubs"></script>
<!--Add script to update the page and send messages.-->
<script type="text/javascript">
$(function () {
// Declare a proxy to reference the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call to broadcast messages.
chat.client.broadcastMessage = function (name, message) {
// Html encode display name and message.
var encodedName = $('<div />').text(name).html();
var encodedMsg = $('<div />').text(message).html();
// Add the message to the page.
$('#discussion').append('<li><strong>' + encodedName
+ '</strong>: ' + encodedMsg + '</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();
});
});
});
</script>
</body>
</html>
My Hub...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
namespace MyTrainer
{
public class ChatHub : Hub
{
public void Send(string name, string message)
{
Clients.All.broadcastMessage(name, message);
}
}
}
My Controller..
public ActionResult ChatRoom()
{
return View();
}
Thank you!
I was rendering fullcalendar scripts in the layout page that was messing with the scripts for signal r
You should catch the error message when connecting to the server,you can add ".fail", one of the errors you may encounter is due to the version.
$.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();
});
}).fail(function (reason) {
console.log("SignalR connection failed: " + reason);
});

Why don't my Javascript prompts show up from my Express.IO .ejs file?

I am relatively new to JavaScript and subsequently Node + Express.IO. I am trying to build a page that will track in real time connections made by different 'users' to the server. Consequently, when I do include all the functions from the io module, my prompt() and alert do not work anymore. I am running nodemon app.js from my terminal and no compilation errors are showing up when I do so. The alert and prompt work again when I remove all the io functions.
These are the contents of my index.ejs <body> tag:
<body>
<h1>Chatroom</h1>
<script>
alert("Hello!");
var name = prompt("What is your name?");
io.connect();
io.emit.('got_a_new_user', {name: name});
io.on('new_user', function(data) {
//render this new info in the HTML
var users = data.users;
console.log(users);
if (users != undefined) {
console.log("\n\n\n" + users);
// if users is defined, append the new division containing the username
}
});
io.on('disconnect_user', function(data) {
var users = data.users;
if (users != undefined) {
// If users is defined remove the corresponding HTML element
}
});
</script>
<div id="container">
</div>
</body>
Any help would be much appreciated.
Adding example for the comment added by UKatz,
You will have to connect socket.io from the client as follows,
index.ejs
<script src="http://ip:port/socket.io/socket.io.js"></script>
<script type="text/javascript">
var socket = io.connect('http://ip:port');
socket.emit('got_a_new_user', {name: name});
</script>
Check socket.io documentation for how to connect socket.io with client.

Play Framework 2.1 websockets in Chrome

I can't seem to get websocket communication to work in the Play Framework version 2.1.
I created a simple test that does nothing but send messages back and forth with a push of a button. All the code for it is below. But nothing shows up except for the button.
Has anybody seen this problem or can someone tell me what I may be doing wrong in the code below?
I am using the latest version of Chrome.
Here is my simple setup.
In Application.java
public static Result index() {
return ok(index.render());
}
public static WebSocket<String> sockHandler() {
return new WebSocket<String>() {
// called when the websocket is established
public void onReady(WebSocket.In<String> in,
WebSocket.Out<String> out) {
// register a callback for processing instream events
in.onMessage(new Callback<String>() {
public void invoke(String event) {
System.out.println(event);
}
});
// write out a greeting
out.write("I'm contacting you regarding your recent websocket.");
}
};
}
In Routes File
GET / controllers.Application.index()
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.at(path="/public", file)
GET /greeter controllers.Application.sockHandler()
In Index.Scala.html
#main(null) {
<div class="greeting"></div>
<button class="send">Send</button>
<script type="text/javascript" charset="utf-8">
$(function() {
var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
var sock = new WS("#routes.Application.sockHandler()")
sock.onmessage = function(event) {
$('.greeting').append(event.data)
}
$('button.send').click(function() {
sock.send("I'm sending a message now.")
});
})
</script>
}
In Main.scala.html
#(title: String)(content: Html)
<!DOCTYPE html>
<html>
<head>
<title>#title</title>
<link rel="stylesheet" media="screen" href="#routes.Assets.at("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="#routes.Assets.at("images/favicon.png")">
<script src="#routes.Assets.at("javascripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
</head>
<body>
#content
</body>
The problem is in
var sock = new WS("#routes.Application.sockHandler()")
you have to specify the protocol and the complete url in the format: ws://localhost:9000/greeter.
Check this question to do it in javascript: How to construct a WebSocket URI relative to the page URI?
you can use a Route's webSocketURL() method to retrieve a url that can be passed to a WebSocket's constructor. Here's an example from Play's websocket-chat sample code:
$(function() {
var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
var chatSocket = new WS("#routes.Application.chat(username).webSocketURL()")
var sendMessage = function() {
chatSocket.send(JSON.stringify(
{text: $("#talk").val()}
))
$("#talk").val('')
}
// ...
So in your code you can use something like
var sock = new WS("#routes.Application.sockHandler().webSocketURL()");
Personally I don't like intermingling interpolated code with JS, since I think that any code executing on the client should only be concerned with the state of the client, and not the server (not to mention it makes refactoring the script out into an external file impossible), so I tend to do something like this:
<div class="container app-container"
data-ws-uri="#routes.Application.WSUri.webSocketURL()">
.......
</div>
Then in my JS I can just do something like
var sock = new WS(document.querySelector(".app-container").dataset.wsUri);
// ....

Categories