SignalR Hub not executing the specified javascript - c#

I am using SignalR in an ASP.Net Web Application project and am having issues. My goal is to make any changes in the administrative side of the site cause some GridViews to refresh. I was planning on doing this by sending the signal for some javascript to be run, thereby refreshing the update panels containing the GridViews.
The issue right now is that I cannot get any of the code my hub is trying to call to execute in the client. I am receiving the following error in FireBug from the jquery.SignalR.js file, but I'm not sure how to proceed to fix it:
Firefox can't establish a connection to the server at ws://localhost:40068/signalr?data=[]&transport=webSockets&clientId=92e4f7b9-0118-4fd9-bb55-5f22338d6162.
(function(n,t){"use strict";if(typeof ...on=n.signalR=i})(window.jQuery,window)
After it throws this error it still looks like it is setting up the connection, but none of the javascript being sent through the hub is executed
I have set up the following hub in my site:
namespace testProject
{
public class statusChanges : Hub
{
public void ServerChange()
{
Clients.serverChange();
}
}
}
I have the following code in my button click event in the admin section. Debugging shows that this code is being run by the server:
var clients = Hub.GetClients<statusChanges>();
clients.serverChange();
Finally I have this code in my page trying to just launch an alert when it receieves the signal to confirm it is working.
<script type="text/javascript">
$(function () {
var statusChange = $.connection.statusChanges;
statusChange.serverChange = function () {
alert(8);
};
$.connection.hub.start();
});
</script>
Does any one have any ideas why this would not run or what the FireBug error means?

The error in firebug is expected. It's the websocket connection failing, don't worry about it as SignalR will fallback to longpolling. You have a method on the server side with the same name as a client side event. That doesn't work.
You want something like this:
public Administration : Hub {
}
Event handler:
var clients = Hub.GetClients<Administration>();
clients.serverChange();
Javascript:
<script type="text/javascript">
$(function () {
var administration= $.connection.administration;
administration.serverChange = function () {
alert(8);
};
$.connection.hub.start();
});
</script>

Related

How can I connect to my SignalR hub from a different host?

I have an ASP.NET MVC 5 app that is running SignalR 2.2.2 this app is running on hub.domain.com. On another Asp.Net MVC-5-based app (i.e. localhost:15371) I want to interact with the hub.
On my localhost:15371 application, I added the following code
<script>
var myHubHost = 'http://hub.domain.com/';
</script>
<script src="http://hub.domain.com/Scripts/jquery.signalR-2.2.2.min.js"></script>
<script src="http://hub.domain.com/signalr/hubs"></script>
<script src="http://hub.domain.com/signalr/custom_code.js"></script>
However, I am getting the following error when trying to connect to the hub on app.domain.com but it is working fine when I run it directly from hub.domain.com
Error: Error during negotiation request.
To enable CORS on my hub app by adding the following to my <system.webServer></system.webServer> section in the Web.config file.
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
I also, tried to enable JSONP and and the detailed errors on my hub like so
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
hubConfiguration.EnableJSONP = true;
app.MapSignalR(hubConfiguration);
}
What could be causing this error? What else needs to be done to connect to my hub from another app?
The code that is used to connect to the my hub is as follow and found in the custom_code.js file.
$(document).ready(function () {
// Reference the auto-generated proxy for the hub.
var app = $.connection.myHubName;
// The getApiUrl() method return http://hub.domain.com/signalr
// as the myHubHost variable is set to http://hub.domain.com/
$.connection.hub.url = getApiUrl('signalr');
$.connection.hub.error(function (error) {
console.log(error)
});
// Create a function that the hub can call back get the new events
app.client.updatePanel = function (message) {
// Do stuff
}
// Start the connection.
$.connection.hub.start();
// This allows me to set a variable to control the base-url host when including this file on a different app.
function getApiUrl(uri)
{
var link = "/";
if (typeof window.myHubHost !== typeof someUndefinedVariableName) {
link = window.myHubHost;
}
return link + uri;
}
});
UPDATED
I enabled logging as per like so
$.connection.hub.logging = true;
I also installed Microsoft.Owin.Cors package to enable cors as per the documentation. Here is my current configuration
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableDetailedErrors = true
};
map.RunSignalR(hubConfiguration);
});
Here is the logs that I get in the console. As you can see, the negotiation fails.
SignalR: Auto detected cross domain url.
SignalR: Client subscribed to hub 'myHubName'.
SignalR: Negotiating with 'http://hub.domain.com/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%5D'.
SignalR error: Error: Error during negotiation request.
SignalR: Stopping connection.
I figured out my problem finally.
I had html base tag in my layout which was causing the problem.
I removed
and my problem was solved!

How to connect the socket.io with backend

I am trying to implement chat in my ionic project what i have tried so far is to connect the socket.io with my backend (c#) is below.
Here is my index.html
<script src="http://192.xxx.x.xxx:8888/socket.io/socket.io.js"></script>
and here i created socketservice.js file looks like
var example = angular.module('starter.socketService',[])
example.service('SocketService',function(socketFactory){
console.log("SocketService");
return socketFactory({
ioSocket: io.connect('http://192.xxx.x.xxx:8888')
});
console.log(socketFactory);
})
finaly i created a folder called server i have a chat-server.js file in there.
var io = require('socket.io')(8888);
console.log(io);
io.on('connection', function(socket){
console.log(socket);
socket.on('send:message', function(msg){
console.log(msg);
socket.emit('message', msg);
console.log("success");
});
});
ERROR:
GET http://192.xxx.x.xxx:8888/socket.io/socket.io.js net::ERR_CONNECTION_TIMED_OUT
What i have done worng is there anything i have to do to connect with server always i am getting this error
Can some one tell me step by step explaination in c# to develop for socket.io

Showing a status message generically within ASP.NET webforms

Within my site master I have an area where I would like to display status (info, success, error, warning) messages.
In my code behind I would like to make calls such as:
MessageSuccess("Some success message");
MessageSuccess("Another success message");
MessageWarning("Warning message");
and then have these messages all display when the page is next rendered.
I have tried a couple of approaches where I:
Save a structure in Session
Read the structure in Page_PreRender() and update some HTML controls
Clear the structure in Page_UnLoad()
However some of the time the messages show just fine, but some of the time by the time PreRender comes around Page_Unload() has been called and nothing displayed because the structure is empty.
Has anyone got a generic working solution that I can use with my WebForms project to "nicely" display status messages?
Once I was using something very close to example described in Displaying a Custom Error Message section of the Working with Partial-Page Rendering Events. It works nicely if you are dealing with asynchronous postbacks. The only downside is that it was designed for exception handling and not for success/warning/etc. notifications.
There is a property AsyncPostBackErrorMessage on ScriptManager which you can use to pass any text message back to the client. Client will retrieve the message in endRequest event handler:
Server code:
// inside Page code:
var scriptManager = ScriptManager.GetCurrent(this /* assuming that this is a Page instance */);
scriptManager.AsyncPostBackErrorMessage = "Hello world";
Client code:
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
function EndRequestHandler(sender, args) {
if (args.get_error() != undefined) {
var errorMessage = args.get_error().message;
args.set_errorHandled(true);
// Do whatever you need to display the message
}
}
Another possible solution would be to add client function calls to the page using ScriptManager.RegisterStartupScript. I can imagine that you can have a NotificationHandler JavaScript object which would have a success, warning, error, etc. functions which you will call from the server side:
protected void Page_PreRender(object sender, EventArgs e)
{
ScriptManager.RegisterStartupScript(this, GetType(), "<Some unique key for script>", "NotificationHandler.success(\"Hello world\")", true);
}

Multiple Chat Session using SignalR

I am using SignalR based on examples from https://github.com/SignalR/Samples. I am new to this but got it to work in my web app for chat room type of concept. But now I am trying to get a user to user chat functionality done using this. How can I do so?
Do I have to setup a separate connection for each of the chat sessions? Meaning user1 on browser1 is chatting with 5 people separately in single page. Do I need to have separate 5 SignalR connection from user1 to the server?
Meaning do I have to render this section next to each of my chat elements for those 5 different end points for user1? or can I just have one SignalR connection? if I only have one how to I update the correct chat controls from the server to display the response from end users?
#section scripts {
<script src="#Url.Content("~/Scripts/jquery.signalR-1.0.0-rc1.min.js")" type="text/javascript"></script>
<script src="/signalR/hubs" type="text/javascript"></script>
<script>
$(function () {
var chat = $.connection.chat;
chat.client.send = function (message) {
$('#message').append('<li>' + message + '</li>');
};
$.connection.hub.start().done(function () {
$('#send').click(function () {
chat.server.send($('#msg').val());
});
});
});
</script>
}
Is there a example somewhere I can use?
From back end u send to the client by his connection id:
// Call send on to a specific connection
Clients.Client(Context.ConnectionId).send(message);
and on the client you get the client id for the hub connection.
$.connection.hub.id

How to stop browser(especially Internet Explorer) from doing super caching of javascript?

I don't know what is going on but this is really evident in IE 8. It loads up my page and my javascript files.
I then have debug lines in my server side code that should get activated when an ajax request from my jquery comes through. Or some other contact with the server such a refreshing the page.
So I have this
var timeout;
var wait = 300000;
$(function()
{
timeout = null;
timeout = setTimeout("SessionTimeOut()", wait);
$.get('SessionTimeOut', null, function(response)
{
timeout = clearTimeout(timeout);
wait = parseInt(response);
timeout = setTimeout("SessionTimeOut()", wait);
});
});
This should run every time the page is loaded and start a timer to monitor if they should be logged out or not. I reset the timer every time they make a request to the server.
Some times when a user logs in they all of a sudden get timed out. So I put a default timer of 5 mins in to see if that would fix the problem.
So now say the user times out since they are inactive for like 30mins. They come back and get sent to my login page. So they are going to a new page. I would hope all this javascript stuff would be destroyed and all the timeout objects would be destroyed.
They then try to log in(Using IE8). Guess what they will get the message that they where timed out since IE8 seems to not want to run this script anymore.
I tried refreshing the page but that does nothing. It seems like once the script has ran it has ran for the entire time the browser is opened.
I have many pages with that uses the code above. Yet once it ran once in one page and you go to another page it won't run again.
The only way to get it to run again is close the browser down or clear all your cache.
So how can I make it run again?
Edit
Here is my server code(well portion of it)
public ContentResult SessionTimeOut()
{
var time = signOut.FigureSessionTime();
// minues 2 mins to make up for any lost time.
double total = time.TotalMilliseconds - 120000;
return Content(total.ToString());
}
So basically the FigureSessionTime out looking inside the users cookie and checks to see if the cookie is by end of session or if they choose to be kept logged in for 2 weeks.
If they choose 2 weeks then 2 weeks worth of milliseconds will be returned back. If it is by session then 30mins of milliseconds will be returned back.
I just take 2 mins of to be on the save side so the client side should always timeout before serverside.
return the time in millseconds
// this is what it returns
1670778.4725000001
Edit 2
Ok so this is what I just did to test some things out.
IE 8
Launched a page that a user does not need to log into. This means no cookie to check there session meaning -120000 will come back. This was verified by an alert box. Since this was like an instant timeout the second that page loaded up I was timed out.
Next I tried to log into a page that was secure and that would take the cookie out check it and return a timeout time back. I had an alert box and checked what was stored in the wait variable.
What the alert box came was -120000 so this should not be. It should be some high number. I was instantly logged out and sent to the login page.
I then went into the "safety tab" in IE 8 and choose "Delete browsing history" a popup came up and I checked all the avaiable options and hit"Delete".
I did this all while being on my site and never left it. So I just typed in my login credentials and logged in.
Now the wait variable has this in it "1677207". So this is like 27mins or something like that.
So why did the first time come back negative? Is it because it first timed out on some other page and cached this or did it just not feel like to work?
I now just tired something else. I cleared the browsing history and closed down IE 8. I then launched my website through VS2008 and loaded it up on my login page.
I then logged in and out 5 times. Each time I logged in I noted the wait time.
This is the results
1678237
1678237
1678237
1678237
1678237
So for 5 times the time was exactly the same not even a millisecond off.
Now lets check firefox.
I did the same thing started my site through VS2008 to launch firefox and go to my signin page.
I logged in 5 times in and out. Each time the alert box came up with the wait time in it I noted it.
This is the results
1677176
1677800
1678003
1677956
1677800
Every single time I logged in it was a different time. So for some reason firefox brought back different results each time but IE8 magically could always do it in the same time not even a millisecond more or less?
I after did what I did before in IE8 I went to a page that would time the user out and return -12000. I went to this page and it did just that and returned me to the sign in page.
I then logged in and the wait time that showed up was "1677940". So it actually went and ran my code and got a different time back. Where IE8 just used the previous -12000 over and over again. I could probably log in a million times and it would always -12000. Once it gets a value it seems to keep that.
Edit 3
You all can try at home now.
Here is what you need
// Javascript file
var timeout;
var wait = 300000;
$(function()
{
timeout = null;
timeout = setTimeout("SessionTimeOut()", wait);
$.get('SessionTimeOut', null, function(response)
{
timeout = clearTimeout(timeout);
wait = parseInt(response);
alert(wait);
timeout = setTimeout("SessionTimeOut()", wait);
});
/* starts every time a ajax request is made */
$().ajaxStart(function(e)
{
timeout = clearTimeout(timeout);
$('body').css('cursor', 'progress');
});
$().ajaxStop(function(e)
{
$('body').css('cursor', null);
});
$().ajaxComplete(function(event, XMLHttpRequest, ajaxOptions)
{
if (timeout == null)
{
timeout = setTimeout("SessionTimeOut()", wait);
}
});
});
// need to have dialog ui javascript for this.
function SessionTimeOut()
{
// $('#content').append('<div id="SessionTimeout" title="Session Time Out">Your session has timed out. You must sigin again.</div>');
// $('#SessionTimeout').dialog(
// {
// height: 140,
// resizable: false,
// modal: true,
// closeOnEscape: false,
// buttons:
// {
// 'Return To Sign In Page': function()
// {
// window.location.href = "/account/signin";
// }
// }
// });
// $('#ui-dialog-title-SessionTimeout').siblings('a').remove();
}
// Index View
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Index</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script src="../../JScript1.js" type="text/javascript"></script>
</head>
<body>
<div>
</div>
</body>
</html>
//TestController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
namespace MvcApplication1.Controllers
{
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Index()
{
return View();
}
public ContentResult SessionTimeOut()
{
Random random = new Random();
return Content(random.Next(100).ToString());
}
}
}
If you run this code in IE8 you will get the same random number each time. Try it in firefox and you wont.
I had a similar problem recently. Disabling caching for may ajax call cleared it out. Try this guy:
var timeout;
var wait = 300000;
$(function()
{
timeout = null;
timeout = setTimeout("SessionTimeOut()", wait);
$.ajax({
url:'SessionTimeOut',
success:function(response) {
timeout = clearTimeout(timeout);
wait = parseInt(response);
timeout = setTimeout("SessionTimeOut()", wait);
},
type:'get',
cache:false
});
});
notice the cache:false option
Seeing as there is no JQuery and ASP.NET experts speaking up, I'll chip in my €0.02: I doubt this is solely a caching issue. I don't speak JQuery fluently enough to understand what your Ajax call is doing but I have a feeling the problem is there rather than in caching. But I can be wrong there.
Anyway, the easiest way to prevent caching of a Javascript file is to append a random timestamp to the URL:
<script language='script.js?timestamp=1020349302930'>
this will make the script load anew on every instance. If you can use only JS, you can use Math.rand to create the random value and then create or document.write the <script> tags. Or of course, use the server side language of your choice. ( I just saw in your tags that that is ASP.NET)
The cleaner way would be setting the right caching headers either in your server configuraiton, or by sending out headers dynamically inside the JS files (which would have to be parsed by a language like PHP or ASP to do that).
Maybe this gives fresh input in hunting down what's wrong. Good luck!
I agree with Pekka that the problem is more likely not to be in the browser caching.
It looks like you're using the $get call to fetch the timeout value from the server. This seems... odd. If that's not what you're trying to do, then why do you parse the response as the timeout value? If that is what you're trying to do, then are you sure that the response that's returned contains the value that you expect it to contain?

Categories