I added SignalR to an existing ASP.Net 4 Web Forms application. Created a new folder called Hubs and added a Hub like so:
[HubName("UpdatesHub")]
public class UpdatesHub : Hub
{
public void DownloadUpdates()
{
// Code Removed
}
}
Added the RouteTable.Routes.MapHubs(); to Application_Start and added the following to the page:
<script src="/Scripts/jquery-1.9.1.js"></script>
<script src="/Scripts/jquery.signalR-1.0.1.js"></script>
<script src="/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// Declare a proxy to reference the hub.
var upd = $.connection.UpdatesHub;
// Code Removed
// Start the connection.
$.connection.hub.start().done(function () {
$('#btnDownload').click(function () {
upd.server.DownloadUpdates();
});
});
});
</script>
But whenever I click the button I just get "Uncaught TypeError: Object # has no method 'DownloadUpdates'". I have tried removing and readding signalr via NuGet but can't seem to get this to work, help!
SignalR camelCases the method names on the server. Try checking if downloadUpdates() exists.
Related
I had a web Application with master page and I need to show a alert to all connected users of my application. I had used the Owin startup class and mapped signal R
Then created a Hub like below
namespace ArtWebApp
{
[HubName("artHub")]
public class ArtWebHub : Hub
{
public void Hello()
{
Clients.All.hello();
}
public void SayMessage()
{
this.Clients.All.showmessage();
}
}
}
Then in the masterpage I added the Javascript as below
<script src="Scripts/jquery-1.6.4.js"></script>
<script src="Scripts/jquery.signalR-2.2.1.js"></script>
<script type="text/javascript">
$(function () {
debugger;
var connection = $.hubConnection("")
var hub = connection.createHubProxy('artHub');
hub.on('showmessage', function () {
alert('Hi');
});
connection.start().done();
//connection.start(function () {
// hub.invoke('SayMessage');
//});
});
</script>
This is working perfectly when the Hub method is invoked from the same page but when I tried to call the method from button click of a page its not working
protected void Button1_Click(object sender, EventArgs e)
{ var hubContext = GlobalHost.ConnectionManager.GetHubContext<ArtWebApp.ArtWebHub>();
hubContext.Clients.All.SayMessage();
}
Can somebody suggest me the issue
What i can see from your code is a mistake on the client side function you are calling.
Clients.All typically lets you invoke a function you have defined at the client side by calling Clients.All.functionName()
In the Button1_Click event please change
hubContext.Clients.All.SayMessage();
To
hubContext.Clients.All.showMessage();
This is because you are using the dynamic collection Clients
You are trying to invoke a client side function (which doesn't exist).
The method SayMessage you are trying to call is a member of the ArtWebHub class and cannot be invoked by calling hubContext.Clients.All.
You can invoke SayMessage from the client using hub.invoke('SayMessage') but to invoke the showmessage function defined in the client you'll have to invoke it differently from the server because SayMessage is not available to the hubContext
We use SignalR library in our ASP.NET web application. The code looks as following:
Server:
[HubName("ticketsCounterHub")]
public class MassivePrintHub : Hub
{
public void PostTicketsCount(long count)
{
Clients.All.Send(count);
}
}
public class HubFactory
{
private HubFactory() {}
public static readonly HubFactory Current = new HubFactory();
public IHubProxy GetMassivePrintHubProxy()
{
var hubConnection = new HubConnection(ConfigUtils.GetRequiredSettingValue("adminPath"));
var hubProxy = hubConnection.CreateHubProxy("ticketsCounterHub");
hubConnection.Start().Wait();
return hubProxy;
}
}
Client (JavaScript):
MassivePrintApp.controller("ListController", function ($scope, Dates) {
var hubManager = (function () {
var massivePrintHub = $.connection.ticketsCounterHub;
$.connection.hub.start();
return { massivePrintHub: massivePrintHub };
} ());
hubManager.massivePrintHub.client.Send = function (ticketsCount) {
$scope.action.Quantity = ticketsCount;
$scope.$digest();
};
});
The key part of code is in MVC controller:
public FileResult PrintAction(int actionId, int count, DateTime actionDate, bool isThermo=false)
{
var ticketsCount = _ticketService.GetTicketsInStatusCount(actionId, actionDate, TicketStatusEnum.ToPrint);
HubFactory.Current.GetMassivePrintHubProxy().Invoke("PostTicketsCount", ticketsCount);
var stream = new MemoryStream();
xmlResponse.Save(stream);
stream.Flush();
stream.Position = 0;
return File(stream,ContentTypeEnum.XML.ToString(),String.Format("массовая {0} мероприятия {1} {2}шт.xml", isThermo?"термопечать":"печать", action.Artist,count));
}
As you can see, we have this line:
HubFactory.Current.GetMassivePrintHubProxy().Invoke("PostTicketsCount", ticketsCount);
And that causes the issue, that is whenever we call it one more instance of hub was added to "Requests" section on IIS.
I understand we already started hub in JavaScript code, but I'm not sure how can I use the existing connection or how to get rid of HubFactory or delete created hub instance.
And I don't understand why hub hangs on IIS.
Starting from a more simple example will help you a lot I guess. After that you can look into hosting your SignalR server differently (Console App or Windows Service) the basics won't change
(First installed SignalR: NuGet: install-package Microsoft.AspNet.SignalR)
I made a simple web-app example. The project has a Hub class:
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SRTest
{
public class MassivePrintHub : Hub
{
private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MassivePrintHub>();
// Can be called from your Javascript code
public void PostTicketsCount(long count)
{
Clients.All.Send(count);
}
// Can be called from your c# code
public static void Static_PostTicketsCount(long count)
{
hubContext.Clients.All.Send(count);
}
}
}
An Owin startup class:
using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SRTest.Startup))]
namespace SRTest
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
app.MapSignalR(hubConfiguration);
}
}
}
Page (Razor just to be able to call a simulator which calls a c# class to post message from backend):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TEST PAGE</title>
<!--Reference the jQuery library. -->
<script src='Scripts/jquery-1.6.4.js'></script>
<!--Reference the SignalR library. -->
<script src='Scripts/jquery.signalR-2.2.0.js'></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="signalr/hubs"></script>
</head>
<body>
THIS IS A TEST PAGE
<!-- Call simulator (trigger event every 5 seconds) -->
#{SRTest.SendFromBackEnd.SimulateSend();}
<script>
$(function () {
var printHub = $.connection.massivePrintHub;
// when send event happens
printHub.client.send = function (count) {
console.log("Send " + count + " tickets");
};
$.connection.hub.start().done(function () {
console.log("Connected");
});
$.connection.hub.logging = true;
});
</script>
</body>
</html>
And I added a dummy class which triggers the event through hubcontext every 5 seconds.
using System.Threading;
using System.Web;
namespace SRTest
{
public class SendFromBackEnd
{
public static void SimulateSend()
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
while (true)
{
MassivePrintHub.Static_PostTicketsCount(2);
Thread.Sleep(5000);
}
}).Start();
}
}
}
I added some loggings to the SignalR, add some debug points, it will help you understand the basics, then it will be much easier to build what you are planning to build.
EDIT
About the hanging request: As long as you have a client connected to your SignalR server with SSE or AJAX Long-Polling, you will have an ongoing request, which never finishes. (In case of AJAX Long-polling, it finishes for very short times and comes back). In the apps where I use only Javascript clients, I only see the request if a page is open where I am listening to events. If no page or static page open then no request.
In the apps where I am using .NET clients, as long as the two apps are running, and both Sartup classes executed, the request will always be there, even if no page open. (Since the .NET client is still listening to events.)
For more info: http://hanselminutes.com/291/damian-edwards-explains-the-realtime-web-for-aspnet-with-signalr
This is a Threading related issue. Try like this
Task.Run(() => connection.Start().ContinueWith(task =>
{
.....
})).Wait();
I am new to SignalR and having a bit of difficulty using a SignalR hub in a self hosted scenario.
At the moment (just for testing) I have the simplest hub possible:
public class NotificationsHub : Hub
{
public void Hello(string name)
{
Clients.All.hello("Hello " + name);
}
}
This hub class is in a Class Library project which is referenced in a Windows Service application. I've added all the nuget packages to the Windows Service app and added the OWIN Startup class which looks like this:
public class Startup
{
public void Configuration(IAppBuilder app)
{
AppDomain.CurrentDomain.Load(typeof(NotificationsHub).Assembly.FullName); // as selfhosting doesn't scan referenced libraries for Hubs
app.Map("/signalr", map => {
map.UseCors(CorsOptions.AllowAll);
var hubConfig = new HubConfiguration {
EnableDetailedErrors = true,
EnableJSONP = true
};
map.RunSignalR(hubConfig);
});
}
}
In the Windows Service OnStart method I host the signalR using:
SignalR = WebApp.Start<Startup>("http://*:9191/");
In the ASP.NET MVC app which should interact with SignalR I have the following code:
<script src="Scripts/jquery.signalR-2.1.1.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="http://localhost:9191/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
$.connection.hub.url = "http://localhost:9191/signalr";
var notif = $.connection.notificationsHub;
notif.client.hello = function (msg)
{
alert(msg);
}
$.connection.hub.start().done(function () {
$("#sayHello").click(function () {
notif.server.hello($("#myName").val());
});
});
});
</script>
The problem is this doesn't work in my correct setup... in the browser console I have no errors, the ~/signalr/hubs js looks fine...
If I do more or less the same configuration, but host the SignalR in the ASP.NET MVC app, everything works as expected.
UPDATE: following #halter73 's suggestion to enable the client side logging for the hub, I've got the following error message which I still can't fix:
SignalR: notificationshub.Hello failed to execute. Error: Method not
found: 'Microsoft.AspNet.SignalR.Hubs.IHubCallerConnectionContext
Microsoft.AspNet.SignalR.Hub.get_Clients()'.
Could somebody please let me know what I am missing?
Thank you in advance!
Andrei
Since 2.1.0, get_Clients should return a IHubCallerConnectionContext<dynamic> instead of IHubCallerConnectionContext.
The error you are seeing could happen if you compile your application against SignalR <= 2.03 but loading SignalR >= 2.10 at runtime.
I'm using the latest version of SignalR (1.0.1). I am trying to broadcast from my controller to the hub and having a few issues:
My client does not seem to be getting messages.
It doesn't seem that my hub context even has an 'addMessage' defined:
My hub:
public class SignalRPriceHub : Hub
{
public void sndMessage(string msg)
{
Clients.All.addMessage(msg + "****");
}
}
Javascript client:
<script src="#Url.Content("~/Scripts/jquery.signalR-1.0.1.min.js")"></script>
<script src="~/signalr/hubs"></script>
.....
var myHub = $.connection.signalRPriceHub;
myHub.client.addMessage = function (message) {
alert(message);
};
Controller:
var context = GlobalHost.ConnectionManager.GetHubContext<SignalRPriceHub>();
context.Clients.All.addMessage("TestOutsideMessage!!!");
A few things I noticed:
1. My hub context doesn't seem to have an 'addMessage'
{"'Microsoft.AspNet.SignalR.Hubs.ClientProxy' does not contain a definition for 'addMessage'"} System.Exception {Microsoft.CSharp.RuntimeBinder.RuntimeBinderException}
If I run the following code from the same file as my client code above, I do get a message.
var myHub = $.connection.signalRPriceHub;
$.connection.hub.start(function () {
myHub.server.sndMessage("Hello World!");
});
Can anyone shed some light as to what might be happening? Thanks all!
I'll go over the faults in your initial application which shed light to why your second bullet point makes it all work.
In your javascript client you must start the connection:
$.connection.hub.start();
You must then request the message on your hub by calling the sndMessage command:
$.connection.hub.start().done(function() {
myHub.server.sndMessage("Hello world");
});
The reason why you do not see an addMessage function on your hub context is because the hub context .Clients.All is dynamic.
One last note, in order to make the sample work you also need to make sure that in your Application_Start you have RouteTable.Routes.MapHubs(); . I assume you already have this since once you add the connection start that everything works.
Not able to get SignalR working in my machine (with IE9). On entering some text and clicking submit, the text is not getting listed as intended. Also, I would expect the list getting updated from multiple instances of browser and It does not happen. There is no error. Could anybody help here?
C#
namespace TestSignalR.Hubs
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for ChatHub.
/// </summary>
public class ChatHub : SignalR.Hubs.Hub
{
public void TestMessage(string message)
{
Clients.writeMessage(message);
}
}
}
ASPX
<input type="text" name="txtInput" id="txtInput" />
<button id="btnSubmit">Submit</button>
<ul id="messages">
</ul>
<script type="text/javascript" src="SignalR/Hubs"></script>
<script type="text/javascript">
$(document).ready(function (message) {
var chat = $.connection.chatHub;
chat.writeMessage = function (message) {
$("#messages").append("<li>" + message + "</li>");
};
$("#btnSubmit").click(function () {
var text = $("#txtInput").val();
chat.testMessage(text);
});
$.connection.hub.start();
});
</script>
Master page has the references for the JQuery and SignalR files:-
<script src="Scripts/jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="Scripts/jquery.signalR-0.5.2.min.js" type="text/javascript"></script>
Today I was working with the same issue.
First you need to add an atribute to your Hub with the name, as following:
[HubName("chathub")]
public class ChatHub : SignalR.Hubs.Hub
The next to do is to change the order of your calls in the javascript. You need to do the connection next to instantiate the hub.
So, the code will be as following:
$(document).ready(function (message) {
var chat = $.connection.chatHub;
$.connection.hub.start();
chat.writeMessage = function (message) {
$("#messages").append("<li>" + message + "</li>");
};
$("#btnSubmit").click(function () {
var text = $("#txtInput").val();
chat.testMessage(text);
});
});
I hope it works for you.
Please install the 1.0 version of SignalR from Nuget as well. From your script references it looks like you are using 0.5.2 and the latest supported version at the time of writing this post is 1.0. Please download Microsoft.AspNet.SignalR from Nuget