SignalR not working : $.connection.client is null or undefined [closed] - signalr

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
After spending two days getting this working with no success, finally I am asking this question here.
Background: I am trying to use SignalR to send real-time data from my desktop application to all web pages.
What I have is, a console application (this just to get concept working then will move it to active project) that needs to send real time data to a webpage built in asp .net. Both are using .Net 4.
In IE9 it shows me error in debug mode at line "chat.client.broadcastMessage = " saying chat.client is null or undefined.
In firfox, it doesn't show me that error but it's not working/not doing anything and the problem is the same as it's not showing me alert('asking for name'); window so I guess it's not getting there and throwing error before that.
Here's my web page code. This is new separate web site project.
<!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" type="text/javascript"></script>
<script src="Scripts/jquery.json-2.2.min.js" type="text/javascript"></script>
<script src="Scripts/json2.js" type="text/javascript"></script>
<!--Reference the SignalR library. -->
<script src="Scripts/jquery.signalR-1.0.1.min.js" type="text/javascript"></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 () {
alert('starting scrip');
// Declare a proxy to reference the hub.
$.connection.hub.url = 'http://<ipaddressORlochost>:8080/chatroom';
alert($.connection.hub);
alert($.connection.hub.url);
var chat = $.connection.chatHub;
// Create a function that the hub can call to broadcast messages.
alert(chat);
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>');
};
alert('asking for name');
// 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({ jsonp:true}).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>
-------------------------
I have tried removing below line and also adding "/signalr" at the end.
$.connection.hub.url = 'http://:8080/chatroom';
Here's my desktop application (server) code.
class Program
{
static void Main(string[] args)
{
using (WebApplication.Start<Startup>(#"http://<ipaddressORlochost>:8080/chatroom"))
{
while (true)
{
// GlobalHost.ConnectionManager.GetHubContext<ChatHub>().Clients.All.addMessage("dsf","asdfd");
Console.WriteLine("Tags sent :" + DateTime.Now.ToString("HH:mm:ss"));
Thread.Sleep(3000);
}
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HubConfiguration { EnableCrossDomain=true };
app.MapHubs(config);
}
}
public class ChatHub : Hub
{
public void Send(string b,string a)
{
try
{
Clients.All.broadcastMessage(b,a);
}
catch { }
}
}
ANY HELP WOULD BE REALLY APPRECIATED.
Thanks All in advance.
-------------- FOUND THE ANSWER ---------- HAVE EDIT THIS QUESTION AS CANNOT ANSWER MY OWN QUESTION WITHIN 8 HOURS
Hi ALL
Just in case if some one else having same problem. I have found answer/fixed.
THANKS TO Hatake Kakashi
Main issue was that $.connection is now changed to $.hubConnection
Here's what I had to change.
Script in my web page. I have left commented code to show what's been replaced with what.
<script type="text/javascript">
$(function () {
alert('starting scrip');
// Declare a proxy to reference the hub.
// $.connection.hub.url = 'http://localhost:8080/chatroom';
var conn = $.hubConnection('http://localhost:8080/chatroom');
alert($.connection.hub);
alert($.connection.hub.url);
var chat = conn.createHubProxy('chatHub'); //$.connection.chatHub;
// Create a function that the hub can call to broadcast messages.
alert(chat);
// 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>');
// };
chat.on('addMessage', function (a, message) {
$('#discussion').append('<li><strong>' + $('<div />').text(a).html()
+ '</strong>: ' + $('<div />').text(message).html() + '</li>');
});
alert('asking for name');
// 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.
conn.logging = true;
// Start the connection
conn.start().done(function () {
alert("Now connected!");
}).fail(function () {
alert("Could not Connect!");
});
// $.connection.hub.start({ jsonp: true }).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>
And on the server side (desktop application), because it's one way only I don't need to anything in my ChatHub
static void Main(string[] args)
{
using (WebApplication.Start<Startup>(#"http://localhost:8080/chatroom"))
{
while (true)
{
GlobalHost.ConnectionManager.GetHubContext<ChatHub>().Clients.All.addMessage("dsf", "Tags sent :" + DateTime.Now.ToString("HH:mm:ss"));
Console.WriteLine("Tags sent :" + DateTime.Now.ToString("HH:mm:ss"));
Thread.Sleep(500);
}
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HubConfiguration { EnableCrossDomain=true };
app.MapHubs(config);
}
}
public class ChatHub : Hub
{
/public void Send(string b, string a)
//{
// try
// {
// Clients.All.addMessage(b, a);
// }
// catch { }
//}
}
Hope this will help others.

Related

How to properly configure Stomp and SockJS endpoint in Spring MVC?

This is/may be duplicate of:
Websocket - InvalidStateError: The connection has not been established yet.
I am implementing Notification System. And want to initialize Socket connection when user Logged In, and show him his notifications, and also if some event happens.
My Code snippet as follows.
websocket.js :
var stompClient = null;
function connect( temp ) {
alert(temp);
//var socket = new SockJS("/websock");
//var socket = new SockJS("/websock"+temp);
var socket = new SockJS(context_path+"/websock"+temp);
//context_path == "/SupportCenter"
stompClient = Stomp.over(socket);
stompClient.connect({}, function( frame ){
console.log( "Connected :- "+frame );
stompClient.subscribe("/topic/notifications", function( notifications ) {
alert( notifications );
});
}, function( error ) {
alert( error );
});
alert();
getNotifications();
}
function getNotifications() {
stompClient.send("/app/hello", {}, "Hiiiiii");
}
WebSocketConfig.java :
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
/* (non-Javadoc)
* #see org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer#registerStompEndpoints(org.springframework.web.socket.config.annotation.StompEndpointRegistry)
*/
#Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/websock").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// TODO Auto-generated method stub
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
}
WebSocketController.java :
#Controller
public class WebSocketController {
#MessageMapping(value="/hello")
#SendTo("/topic/notifications")
public Notify hello() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Notify notify = new Notify();
notify.setMessage("Hello World !!!");
return notify;
}
}
Some code Hom.jsp :
<script type="text/javascript" src="<c:url value="/resources/js/sockjs.min.js"/>"></script>
<script type="text/javascript" src="<c:url value="/resources/js/stomp.min.js"/>"></script>
<script type="text/javascript" src="<c:url value="/resources/js/websocket.js"/>"></script>
<script type="text/javascript">
$(document).ready(function() {
//...
connect( '${nsec}');
});
Why Firefox Console giving XML Parsing Error: no root element found Location: while in Network tab status code is 200 OK.
Console Tab
Network Tab
Originaly posted to this question.
This is because stompClient.connect() method is asynchronous. I doesn't pause the execution waiting until connection is established. When you call getNotifications() right after alert() most probably connection is not established yet (it might be established if alert() takes enough time to connect).
You are supposed to call getNotifications() in stompClient.connect() callback (just like you do with stompClient.subscribe()) to be sure that connection is established by the time it gets invoked.
For example:
stompClient.connect({}, function( frame ){
console.log( "Connected :- "+frame );
stompClient.subscribe("/topic/notifications", function( notifications ) {
alert( notifications );
});
getNotifications();
}, function( error ) {
alert( error );
});
Besides of that you may consider using #SubscribeMapping annotation in your java code to get rid of explicit message from JavaScript to get initial message from the server. This way the server sends initial message as soon as subscription is established.
For example:
#MessageMapping(value="/hello")
#SubscribeMapping("/notifications")
#SendTo("/topic/notifications")
public Notify hello() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Notify notify = new Notify();
notify.setMessage("Hello World !!!");
return notify;
}
Then client code would look like following:
stompClient.connect({}, function( frame ){
console.log( "Connected :- "+frame );
stompClient.subscribe("/topic/notifications", function( notifications ) {
alert( notifications );
});
}, function( error ) {
alert( error );
});

SignalR : How can I broadcast message to Other page of the application

I am creating a test app, where one can download some files and on download success notification will be propagated to admin ,something like notification in
www.ge.tt,or panel notification in Facebook.
I have two pages
a)Download.aspx
b)LandingPage.aspx
In Download.aspx
function PushNotification() {
alert("I ran Upto Here");
//Declare a proxy to Reference a Hub
var notification = $.connection.notificationHub;
//Start a Connection
$.connection.hub.start().done(function () {
notification.server.send(21);
//$("#hdnFileId").val()
alert("I ran Upto Here 2 ");
});
notification.client.broadcastMessage = function (FileID) {
alert("file was Downloaded" + FileID);
};
}
Here two different tabs/browser are working Fine showing alert message if page Loads.
but i want to use the brodcast message in my LandingPage.aspx
here is the Js
$(function () {
var notification = $.connection.notificationHub;
notification.client.broadcastMessage = function (FileID) {
alert("file was Downloaded" + FileID);
};
});
And my hubclass ..
namespace TestApplication.Entities
{
public class NotificationHub : Hub
{
//public void Hello()
//{
// Clients.All.hello();
//}
public void Send(int FileID)
{
Clients.All.broadcastMessage(FileID);
}
}
}
but the notification is not coming here, whats wrong Here?
You didn't start connection in LandingPage.aspx
Try like this in LandingPage.aspx
var notification = $.connection.notificationHub;
$.connection.hub.start();
notification.client.broadcastMessage = function (FileID) {
alert("file was Downloaded" + FileID);
};

SignalR - Javascript Hub Proxies

When you use SignalR, in your HTML you need to reference the following two scripts:
<script src="~/Scripts/jquery.signalR-1.0.0.js"></script>
<script src="/signalR/hubs"></script>
The second one is for a JavaScript hub proxy which will be auto generated. Everything works fine. However what happens if the JavaScript Hub Proxy generation is disabled somehow, perhaps by setting DisableJavaScriptProxies property (https://github.com/SignalR/SignalR/commit/7e974f4e92551a26f3e3e0a166e1dbf6c064e850). When JavaScript proxy generation is disabled and you try to reference /signalr/hubs in your HTML, it gives the JavaScript error:
Uncaught Error: SignalR: JavaScript Hub proxy generation has been disabled.
When I browse to that path in the browser, the response is:
throw new Error('SignalR: JavaScript Hub proxy generation has been disabled.')
If the JavaScript proxy generation is disabled, how is the $.connection.myHub.client JavaScript code going to work? What extra do I have to do to make it work? The JavaScript error I get is
Uncaught TypeError: cannot read property 'client' of undefined.
You can create the proxies yourself. See here.
This is also done in the samples project within the SignalR source. See the MouseTracking example. JS for it (from here):
/// <reference path="../../Scripts/jquery-1.8.2.js" />
/// <reference path="../../Scripts/jquery.signalR.js" />
$(function () {
var hubConnection = $.hubConnection('/signalr', { qs: 'test=1', logging: false, useDefaultPath: false }),
hub = hubConnection.createHubProxy('mouseTracking');
hub.on('move', updateCursor);
function updateCursor(id, x, y) {
var e = document.getElementById(id);
if (!e) {
e = $('<div id="' + id + '"><i class="icon-screenshot"></i>' + id + '</div>').appendTo(document.body);
e.css('position', 'absolute');
}
else {
e = $(e);
}
e.css({ left: x + 15, top: y + 15 });
}
hubConnection.logging = true;
hubConnection.start({ transport: activeTransport })
.pipe(function () {
return hub.invoke('join');
})
.pipe(function () {
$(document).mousemove(function (e) {
hub.invoke('move', e.pageX, e.pageY);
updateCursor(hub.state.id, e.pageX, e.pageY);
});
});
});
You may have disabled it in your Startup class, like so:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
hubConfiguration.EnableJavaScriptProxies = false;
app.MapSignalR("/signalr", hubConfiguration);
}
}
I had the code above. Removing/commenting out this line: hubConfiguration.EnableJavaScriptProxies = false; should give you proxy generation.
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
app.MapSignalR("/signalr", hubConfiguration);
}
}
For everybody who stumbles on this issue. It seems to be by design, and even the SignalR utility generates only server proxy methods.
It will not create client methods, even if you have a strongly typed Hub (Client interface).
So, the only correct answer, should be that you should generate small functions, as documented at Microsoft.
As in the stockticker sample:
$.connection.hub.start()
.then(init)
.then(function () {
return ticker.server.getMarketState();
})
.done(function (state) {
if (state === 'Open') {
ticker.client.marketOpened();
} else {
ticker.client.marketClosed();
}
The stockticker itself is defined like this
public class StockTickerHub : Hub
and the interface
public interface IClientStock
{
void MarketOpened();
void MarketClosed();
void MarketReset();
void UpdateStockPrice(Stock stock);
}
So for each client proxy method, repeat this. This should not break any bodies project targets.
$.extend(ticker.client, {
updateStockPrice: function (stock) {
var displayStock = formatStock(stock),
$row = $(rowTemplate.supplant(displayStock)),
$li = $(liTemplate.supplant(displayStock)),
bg = stock.LastChange < 0
? '255,148,148' // red
: '154,240,117'; // green
$stockTableBody.find('tr[data-symbol=' + stock.Symbol + ']')
.replaceWith($row);
$stockTickerUl.find('li[data-symbol=' + stock.Symbol + ']')
.replaceWith($li);
$row.flash(bg, 1000);
$li.flash(bg, 1000);
},
marketOpened: function () {
$("#open").prop("disabled", true);
$("#close").prop("disabled", false);
$("#reset").prop("disabled", true);
scrollTicker();
},

Signalr Owin simple example javascript client not being called

I have a 5.3.0 version of signalr self hosting that is being upgraded to a newer version of signalr.
Using https://github.com/SignalR/SignalR/wiki/Self-host example i have created a simple example, but i can’t get it to work.
I can get a connection to the hub on the server and call methods on the hub, but i can’t get the hub to call the javascript client.
When looking at it in fiddler I never see a response come back from the hub.
Here is the code
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Hosting;
using Owin;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
string url = "http://localhost:8080/";
using (WebApplication.Start<Startup>(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
}
}
using Microsoft.AspNet.SignalR;
using Owin;
namespace ConsoleApplication3
{
class Startup
{
// This method name is important
public void Configuration(IAppBuilder app)
{
var config = new HubConfiguration
{
EnableCrossDomain = true,
EnableJavaScriptProxies = true
};
app.MapHubs(config);
}
}
}
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using Newtonsoft.Json;
namespace ConsoleApplication3.Hubs
{
public class Chat : Hub
{
public override Task OnConnected()
{
Notify(Context.ConnectionId);
return new Task(() => { });
}
public void RunTest()
{
Notify(Context.ConnectionId);
}
public void Notify(string connectionId)
{
dynamic testMessage = new
{
Count = 3,
Message = "Some test message",
Timestamp = DateTime.Now
};
String json = JsonConvert.SerializeObject(testMessage);
var context = GlobalHost.ConnectionManager.GetHubContext<Chat>();
context.Clients.Client(connectionId).sendNotification(json);
}
}
}
And here is the client side
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="Scripts/json2.js"></script>
<script src="Scripts/jquery-1.9.1.js"></script>
<script src="Scripts/jquery.signalR-1.0.1.js"></script>
<script src="http://localhost:8080/signalr/hubs"></script>
<script>
$(function () {
// Proxy created on the fly
var notification = $.connection.chat;
$.connection.hub.logging = true;
// Declare functions that can be run on the client by the server
notification.client.sendNotification = onAddNotification;
notification.client.disconnected = function (connectionid) {
console.log(connectionid);
};
// Testing code only
$("#testButton").click(function () {
// Run test function on server
notification.server.runTest();
});
jQuery.support.cors = true;
// Map the onConnect and onDisconnect functions
notification.client.connected = function () {
alert("Notification system connected");
};
notification.client.disconnected = function () { };
$.connection.hub.url = "http://localhost:8080/signalr";
//$.connection.hub.start();
$.connection.hub.start(function () {
alert("Notification system connected");
});
});
// Process a newly received notification from the server
function onAddNotification(message) {
// Convert the passed json message back into an object
var obj = JSON.parse(message);
var parsedDate = new Date(parseInt(obj.Timestamp.substr(6)));
// Update the notification list
$('#notifications').prepend('<li>' + obj.Message + ' at ' + parsedDate + '</li>');
};
</script>
</head>
<body>
Send test
<ul class="unstyled" id="notifications">
</ul>
</body>
Any ideas would be appreciated, since i am fairly stuck.
Few things in your code:
Change this:
public override Task OnConnected()
{
Notify(Context.ConnectionId);
return new Task(() => { });
}
To:
public override Task OnConnected()
{
Notify(Context.ConnectionId);
return base.OnConnected();
}
Also in your hub:
This function is trying too hard:
public void Notify(string connectionId)
{
dynamic testMessage = new
{
Count = 3,
Message = "Some test message",
Timestamp = DateTime.Now
};
String json = JsonConvert.SerializeObject(testMessage);
var context = GlobalHost.ConnectionManager.GetHubContext<Chat>();
context.Clients.Client(connectionId).sendNotification(json);
}
I'm not even sure why you're passing the connection id (maybe it was meant to be static?)
public void Notify()
{
dynamic testMessage = new
{
Count = 3,
Message = "Some test message",
Timestamp = DateTime.Now
};
Clients.Client(Context.ConnectionId).sendNotification(testMessage);
}
You don't need to serialize twice, we already do it for you.
Remove:
jQuery.support.cors = true;
Never set that.
Also:
// Map the onConnect and onDisconnect functions
notification.client.connected = function () {
alert("Notification system connected");
};
notification.client.disconnected = function () { };
These aren't mapping anything client side. You can't map connected and disconnected from the server to the client. The client has its own events.
Other things:
This should be inside of the start callback so that you don't hit it before it's ready:
$.connection.hub.start().done(function() {
// Testing code only
$("#testButton").click(function () {
// Run test function on server
notification.server.runTest();
});
});

Unable to send message to group in SignalR

I am using SignalR library. I am running 3 instances of my application and then I add two users to a group named 'Test'. Now when i send message to 'Test' group, the message is not delivered at all.
public class ChatHub : Hub
{
public void send(string name, string message)
{
//This line of code is not working
Clients.Group("test").broadcastMessage(message);
//This is working
//Clients.All.broadcastMessage(name, message);
}
public void JoinGroup(string groupName)
{
Groups.Add(this.Context.ConnectionId, groupName);
}
public void RemoveGroup(string groupName)
{
Groups.Remove(this.Context.ConnectionId, groupName);
}
}
//Client side
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<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="groupName" />
<input type="button" id="joinGroup" value="Join" />
<br />
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<ul id="discussion">
</ul>
</div>
<script type="text/javascript" src="Scripts/jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="Scripts/j`enter code here`query.signalR-1.0.0-rc1.js"></script>
<script type="text/javascript" src="/signalr/hubs"></script>
</body>
<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();
});
$('#joinGroup').click(function () {
// Call the Send method on the hub.
chat.server.joinGroup($('#groupName').val());
});
});
});
</script>
</html>
Actually the 'broadcastMessage' on the client was expecting two parameter and i was passing only one parameter while calling 'broadcastMessage' using group.
Changing
'Clients.Group("test").broadcastMessage(message);'
to
'Clients.Group("test").broadcastMessage(name, message);' worked.

Resources