SIgnal R hub class not defined..Error loading Hubs - signalr

I am developing a real time application based on signal R . I am using .NET framework 4 , Signal R version 1.2.2 in VS 2010.I am getting a Hub reference error stating
Uncaught Error: SignalR: Error loading hubs. Ensure your hubs reference is correct, e.g. <script src='/signalr/hubs'></script>.
I got a solution to add the Hub reference in global file. But since i am using DNN framework it contains multiple projects and have a common global file.
RouteTable.Routes.MapHubs("/myhubs", new HubConfiguration());
i tried adding this piece of code there, but it too didn't works..
my hub class
public class ChatHub : Hub
{
public void Send(string message)
{
Clients.Others.receive(message);
}
}
And start up class is
[assembly: OwinStartup(typeof(DotNetNuke.Modules.VideoChat.Startup))]
namespace DotNetNuke.Modules.VideoChat
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapHubs();
}
}
}
i am using jquery on client side.
var chat = $.connection.chatHub;
$.connection.hub.start().done(function () {}
Can anyone suggest a way around

You need to follow these steps:
Create a Hub class on the server that inherits the Hub class from SignalR
Create client proxy for the Hub class (using .NET class or javascript code)
Startup the Hub on the server using MapHubs() (obsolete)
Your question does not give enought information. Is it a web application? Are you using javascript or .NET on the client side?
See this post: SignalR hubclass in classlibrary
EDIT
Here is what you should have in your Startup class now that I see that you are using OWIN:
[assembly: OwinStartup("StartupConfiguration", typeof(DotNetNuke.Modules.VideoChat.Startup))]
namespace DotNetNuke.Modules.VideoChat
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// SignalR Hub Startup
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
hubConfiguration.EnableJavaScriptProxies = true;
hubConfiguration.EnableJSONP = false;
app.MapSignalR(hubConfiguration);
}
}
}
In your web.config, add these lines:
<appSettings>
<add key="owin:appStartup" value="StartupConfiguration" />
<add key="owin:AutomaticAppStartup " value="true" />
</appSettings>

Related

What causes SignalR to receive net::ERR_CONNECTION_RESET on connect?

I have a simple SingulaR example that I've added to a legacy ASP.Net MVC application.
Here are the various parts:
OWIN Startup class
[assembly: OwinStartup(typeof (Startup))]
namespace MyApp.Web
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
SignalR Hub
using System.Collections.Generic;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace MyApp.Web
{
[HubName("podService")]
public class PodServiceHub : Hub
{
public PodServiceHub()
{
;
}
public IEnumerable<string> GetMessages()
{
return new[] {"blah", "blah", "blah"};
}
}
}
Server-side facade
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace MyApp.Web
{
public class PodService
{
PodService(IHubConnectionContext<dynamic> clients)
{
Clients = clients;
}
public PodService()
: this(GlobalHost.ConnectionManager.GetHubContext<PodServiceHub>().Clients)
{
}
IHubConnectionContext<dynamic> Clients { get; set; }
public void SendMessageToClient(string message)
{
Clients.All.doSomething(message);
}
}
}
Portions of startup Javascript:
var podService = $.connection.podService;
...
$.extend(podService.client, {
doSomething: function(message) {
console.log("received message:" + message);
}
});
// test
$.connection.hub.start()
.done(function() {
podService.server.getMessages()
.done(function(messages) {
console.log("received message:" + message);
});
});
Within one of the controllers called by the first page:
_podService.SendMessageToClient("Hello from the server!");
Upon executing the application, the following error is displayed in the console of Chrome's dev tools:
WebSocket connection to 'ws://localhost:62025/signalr/connect?transport=webSockets&clientProtocol=1.5&connectionToken=02LJFqBcRBWKXAOlaSwgMPWG0epV7AFl19gNjFCvA0dxD2QH8%2BC9V028Ehu8fYAFN%2FthPv65JZKfK2MgCEdihCJ0A2dMyENOcdPkhDzEwNB2WQ1X4QXe1fiZAyMbkZ1b&connectionData=%5B%7B%22name%22%3A%22podservice%22%7D%5D&tid=6' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET
After this error, however, the podService.server.getMessages() returns with the message from the server printing ["blah", "blah", "blah"] to the console and subsequently the doSomething client function is invoked printing "received message: Hello from the server!".
The calls from both the client and the server are transmitting data, so this error doesn't appear to be breaking the app. It definitely seems to be an issue though. The code above was based upon the sample code generated by the Microsoft.AspNet.SignalR.Sample NuGet package which doesn't display the same behavior. The only difference I'm aware of between my example and NuGet-based sample is that I've added this to a legacy MVC app vs. a pure OWIN-based app. Based upon a comment I read on this SO question this shouldn't be an issue.
So, what's wrong with this example usage and/or what could be causing the connection reset?
I made sure:
the web socket component is enabled in IIS
and the "allowKeepAlive" setting is not set to false in my web.config
But in my case the problem was caused by a packages version mismatch:
In the packages.config Microsoft.Owin.Host.SystemWeb version 2.1.0 was referenced accidentally
<package id="Microsoft.Owin.Host.SystemWeb" version="2.1.0" targetFramework="net452" />
While all the other Owin related packages were referencing version 3.0.1
I updated Microsoft.Owin.Host.SystemWeb to version 3.0.1
Then I had to make sure in the web.config file the "httpRuntime" element targeted the framework version 4.5
<system.web>
<httpRuntime targetFramework="4.5" />
</system.web>
The two steps above solved the problem.
Just ran in to this one myself. In my case the answer seems to be enabling WebSockets for IIS.
Enable WebSockets in IIS 8.0
It works because signalR falls back to one of the following depending on the capabilities of the browser and server.
Server Sent Events.
Forever Frame
AJAX Long Polling
For more information on the transports used and their fallbacks see here
In my case, I had to remove
<httpProtocol allowKeepAlive="false" />
from our web.config (it was there for historical reasons).
In my Case I was using
string sqlConnectionString = ConfigurationManager.ConnectionStrings["GAFI_SignalR"].ConnectionString;
GlobalHost.DependencyResolver.UseSqlServer(sqlConnectionString);
The problem was accessing the database when the user didin't have permission to connect to the database.

How to get SignalR Hub Context in a ASP.NET Core?

I'm trying to get the context for a hub using the following:
var hubContext = GlobalHost.ConnectionManager.GetHubContext<SomeHub>();
The problem is that GlobalHost is not defined. I see it is part of the SignalR.Core dll. At the moment, I have the following in my project .json file, under dependencies:
"Microsoft.AspNet.SignalR.Server": "3.0.0-*"
If I add the latest available version of Core:
"Microsoft.AspNet.SignalR.Server": "3.0.0-*",
"Microsoft.AspNet.SignalR.Core" : "2.1.2"
I get a whole bunch of errors because server and core are conflicting. If I change them to both use version "3.0.0-*", all the conflicts go away, but GlobalHost cannot be found. If I remove Server, and just user Core version 2.1.2 then GlobalHost works, but all the other things needing Server, obviously do not.
Any ideas?
IConnectionManager does not exist any more in SignalR for ASP.Net Core.
I've been using HubContext for getting access to a hub.
public class HomeController : Controller
{
private readonly IHubContext<LiveHub> _hubContext;
public HomeController(IHubContext<LiveHub> hubContext)
{
_hubContext = hubContext;
}
public void SendToAll(string message)
{
_hubContext.Clients.All.InvokeAsync("Send", message);
}
}
I'm using .net core 2.0.0 and SignalR 1.0.0-alpha1-final
Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager is a DI injected service through which you can get the hub context...For example:
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Infrastructure;
using Microsoft.AspNet.Mvc;
public class TestController : Controller
{
private IHubContext testHub;
public TestController(IConnectionManager connectionManager)
{
testHub = connectionManager.GetHubContext<TestHub>();
}
.....
To use the hub in a backgroud service, in addition to controllers, you must use the IHostedService interface and get the hub by DI.
public class MyBackgroundService : IHostedService, IDisposable
{
public static IHubContext<NotifierHub> HubContext;
public MyBackgroundService(IHubContext<NotifierHub> hubContext)
{
HubContext = hubContext;
}
public Task StartAsync(CancellationToken cancellationToken)
{
//TODO: your start logic, some timers, singletons, etc
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
//TODO: your stop logic
return Task.CompletedTask;
}
public void Dispose()
{
}
}
Then you can call your hub from anywhere in your code from HubContext static field:
MyBackgroundService.HubContext.Clients.All.SendAsync("UpdateData", myData).Wait();
Learn more about IHostedService:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.1
You can create and start a timer in MyBackgroundService and call the hub in ElapsedEvent.
I needed to be able to access the Hub Context from outside the app request thread - because I was subscribing to NServicebus messages, and needed to be able to trigger a client function when I received a message.
Here's how I got it sorted:
public static IServiceProvider __serviceProvider;
then during startup configuration
app.UseServices(services =>
{
__serviceProvider = new ServiceCollection()
.BuildServiceProvider(CallContextServiceLocator.Locator.ServiceProvider);
});
Then anywhere else in the vNext asp.net application (any other thread)
var manager = Startup.__serviceProvider.GetRequiredService<IConnectionManager>();
var hub = manager.GetHubContext<ChatHub>();
Hope this helps!
I added some code to my Startup.cs to grab reference to the ConnectionManager which you can then use to do a GetHubContext at anytime from anywhere in your code. Similar to Nimo's answer but a little different, maybe simpler.
services.AddSignalR(options =>
{
options.Hubs.EnableDetailedErrors = true;
});
var provider = services.BuildServiceProvider();
//Hold on to the reference to the connectionManager
var connManager = provider.GetService(typeof(IConnectionManager)) as IConnectionManager;
//Use it somewhere else
var hub = connManager.GetHubContext<SignalHub>();
I'm looking at SignalR source code and it seems that IHubContext is registered as a singleton.
Which means you get the same instance whenever you access it.
Which means you can simply save it in a static var and use it from whatever.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHubContext<MyHub> hubContext)
{
_staticVar = hubContext;
}
But be warned - it's an anti-pattern.

Self hosted SignalR method not called

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.

SignalR as WCF web socket service

Is it possible to host SignalR as a part of WCF websocket service and not as a part of ASP.net web site. I am aware about pushing mesage from a web service to signalR clients but is it also possible tht when the socket connection is opened from browser it maps to a web serivce contract?
You can self-host the SignalR server:
Taken from (https://github.com/SignalR/SignalR/wiki/QuickStart-Hubs):
Getting Started
To get started, Install the following packages:
Install-Package Microsoft.Owin.Hosting -pre
Install-Package Microsoft.Owin.Host.HttpListener -pre
Install-Package Microsoft.AspNet.SignalR.Owin -pre
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Hosting;
using Owin;
namespace SignalR.Hosting.Self.Samples
{
class Program
{
static void Main(string[] args)
{
string url = "http://172.0.0.01:8080";
using (WebApplication.Start<Startup>(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
// This will map out to http://localhost:8080/signalr by default
// This means a difference in the client connection.
app.MapHubs();
}
}
public class MyHub : Hub
{
public void Send(string message)
{
Clients.All.addMessage(message);
}
}
}
You can host the SignarR hub in any .Net application, like:
public class Program
{
public static void Main(string[] args)
{
// Connect to the service
var hubConnection = new HubConnection("http://localhost/mysite");
// Create a proxy to the chat service
var chat = hubConnection.CreateProxy("chat");
// Print the message when it comes in
chat.On("addMessage", message => Console.WriteLine(message));
// Start the connection
hubConnection.Start().Wait();
string line = null;
while((line = Console.ReadLine()) != null)
{
// Send a message to the server
chat.Invoke("Send", line).Wait();
}
}
}
Ref: https://github.com/SignalR/SignalR/wiki/QuickStart-Hubs
If there any specific reason you want to use WCF? you can write your service as SignarR hub only.

signalr example not working

i just installed the signalr sample (downloaded with nuget)
everything from nuget installed fine and it's a clean project (just to test the sample), yet i get the following error:
throw "SignalR: Connection must be started before data can be sent. Call .start() before .send()";
use package manager
install-package Microsoft.Owin.Host.SystemWeb
and do changes in startup.cs
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(Microsoft.AspNet.SignalR.StockTicker.Startup), "Configuration")]
namespace Microsoft.AspNet.SignalR.StockTicker
{
public static class Startup
{
public static void Configuration(IAppBuilder app)
{
Microsoft.AspNet.SignalR.StockTicker.Startup.ConfigureSignalR(app);
}
public static void ConfigureSignalR(IAppBuilder app)
{
app.MapSignalR();
}
}
}
Replace code in Startup.cs file with the following code block, that will fix the js error hopefully
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(Microsoft.AspNet.SignalR.StockTicker.Startup))]
namespace Microsoft.AspNet.SignalR.StockTicker
{
public static class Startup
{
public static void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
you have first to call,
$.connection.hub.start
for example :
var myConnection = $.connection.myConnection;
$.connection.hub.start({ transport: 'auto' }, function () {
alert('connected');
});
/// now you can do what ever you want.
myConnection.SendHello('Just Testing');
now when you load open the page, you should see the browser message (connected), to make sure that the signalR has established a connection.
You can find a full working demo with source code at :
Example including VS2010 solution
This worked for me first time.

Resources