SignalR Windows Service Won't Connect To Hub - c#

I am using SignalR in my web project. I first created the hub as a console application, to allow for easier debugging, it worked flawlessly. I recently tried to switch SignalR over to a windows service and I keep getting the error Uncaught TypeError: Cannot read property 'client' of undefined when trying to reference client on any function
$.connection.hub.url = "https://localhost:8080/signalr";
var dc = $.connection.deviceController
dc.client.anything = ...
This is odd, because I can navigate to https://localhost:8080/signalr/hubs manually without issue. My service app is almost an exact replica of the console app, simply just starting the hubs in the OnStart() method.
StartUp.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
OnStart in service
protected override void OnStart(string[] args)
{
Status("Service starting...");
const string url = "https://*:8080";
try
{
WebApp.Start<Startup>(url);
}
catch (Exception e)
{
Status(e.ToString());
throw;
}
}
Any insight here?
EDIT: I may also point out that deviceController hub is in a referenced class library, but I didn't think that would be an issue since it is referenced properly.

Related

How to implement SignalR authorisation into .Net console

I have a problem with the implementation of authorization in my project.
My project is to create a program (chat) in WinForms using SignalR.
I plan to create two applications: client (WinForms) and server (Console).
I currently don't know how to implement user authorization. I have read SignalR documentation and there is an example based on cookies. Unfortunately, I do not know how to implement it in the console because this example is in the web application. I was looking for some tips on the Internet but unfortunatelly there is almost nothing.
class Program
{
static void Main(string[] args)
{
string url = "http://localhost:8085";
using (WebApp.Start<Startup>(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
}
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);
}
}
I want to add a remote login feature into the server. The problem is that I don't know how to do it from the console application level. The documentation only shows how to do this in a web application.

OnIncomingError of HubPipelineModule not tiggered

In a SignalR project I have the following in order to log exceptions:
HubExceptionHandler.cs:
public class HubExceptionHandler : HubPipelineModule
{
protected override void OnIncomingError(ExceptionContext exceptionContext, IHubIncomingInvokerContext invokerContext)
{
Panic.EmailIt(exceptionContext.Error, "Exception in hub");
base.OnIncomingError(exceptionContext, invokerContext);
}
}
Startup.cs:
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
GlobalHost.HubPipeline.AddModule(new HubExceptionHandler());
GlobalHost.DependencyResolver.Register(
typeof(MonitoringHub),
() => new MonitoringHub(new DashboardService()));
app.MapSignalR();
}
In one of the hub's function all I do is throw an exception:
public void AddDecisionServiceApiLog()
{
throw new Exception();
}
The code in the Hub pipeline Module never gets hit. When the exception is thrown all I get is an empty response on the client.
I tried overriding the BuildIncoming function in the HubExceptionHandler.cs and it works fine so I know the module is being registered successfully.
My guess is that there is something handling the exception somewhere else?
Any ideas?
If your application is an OWIN application, you need to register the HubPipelineModule in a different way.
This link is from the Autofac documentation, but shows an example of how to register it properly.
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Get your HubConfiguration. In OWIN, you'll create one
// rather than using GlobalHost.
var config = new HubConfiguration();
app.MapSignalR("/signalr", config);
// To add custom HubPipeline modules, you have to get the HubPipeline
// from the dependency resolver, for example:
var hubPipeline = config.Resolver.Resolve<IHubPipeline>();
hubPipeline.AddModule(new MyPipelineModule());
}
}

Starting a WCF from its own class constructor

I have a self hosted named pipes (not using http) wcf hosted in a class library. I am able to start the WCF by using the following method in the class library:
ServiceHost serviceHost;
public void startService()
{
// Create the service host
...
// Open Service Host
serviceHost.Open();
}
And then from a winforms test program running the following from a button click:
MyClassLib.MySvc testSvc;
private void button2_Click(object sender, EventArgs e)
{
testSvc = new MyClassLib.MySvc();
testSvc.startService();
}
This does correctly start the WCF running in the class library.
But this requires the winforms that is referencing the class library to call startService method.
What I would like is just to be able to start the service as soon as a reference to the class library that will be running the WCF is done.
I have attempted to add the following in the class library service's constructor:
public MySvc()
{
startService();
}
And then instantiate from the winforms:
MyClassLib.MySvc testSvc;
private void button2_Click(object sender, EventArgs e)
{
testSvc = new MyClassLib.MySvc();
//testSvc.startService(); //No need to call this
}
If I debug the code, I can see that in fact it does break at this point:
public MySvc()
{
startService(); // It does run this but service does not start
}
But this does not run the service. Any help would be appreciated.
Note #1: I believe its some type of timing issue where it does not let you start the service during the constructor method but not sure of that.
Problem resolved and yes my assumption that it was a timing issue (See Note# 1 above) was correct!
To replicate, change this:
public MySvc()
{
startService(); // It does run this but service does not start
}
To this and problem solved:
public void delayStartService()
{
Task.Delay(1000).ContinueWith(t => startService());
}
public MySvc()
{
delayStartService();
}

SignalR Client to MVC5

I'm trying to hit my MVC5 SignalR Hub via a separate, tiny client application, to no avail.
Some background:
I have a regular ASP.NET application using SingalR 1.10, that I can hit with my client. Code:
ASP.NET Hub:
namespace SignalrTest
{
public class ScanHub : Hub
{
public void SendScan(string data, string xmlData)
{
Clients.All.broadcastMessage(data, xmlData);
}
}
}
Client:
connection = new HubConnection("http://localhost:2446/");
hubProxy = connection.CreateHubProxy("ScanHub");
connection.Start();
........
private static async Task RunAsync()
{
object[] param = new object[2];
param[0] = _Data;
param[1] = _xmlData;
await hubProxy.Invoke("SendScan", param);
}
and again, that's working fine. My MVC Hub is identical to the other (I've made sure to change the client HubConnection address), and I have my Startup.cs as:
[assembly: OwinStartupAttribute(typeof(SignalrTest.Startup))]
namespace SignalrTest
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
running my client, it fires off with no errors, but I get no response or any indication that anything has occurred on the MVC side.
Can anyone see where I'm going wrong with the MVC app? I'm unclear on whether I need to alter the routing. I'm happy to post any other code that would help resolve my issue. Thankyou in advance.
Are you really using SignalR 1.1? SignalR 1.1 doesn't use OWIN startup classes, and the MapSignalR method shouldn't even compile.
Try throwing your connection on the .NET client into an async method like so and doing a quick test if your connection is good or not.
private async void Connect()
{
connection = new HubConnection("http://localhost:2446/");
hubProxy = connection.CreateHubProxy("ScanHub");
await connection.Start();
//If using WPF you can test like so if not use whatever output method you prefer to see if it connects
if (Connection.State == Microsoft.AspNet.SignalR.Client.ConnectionState.Connected)
{
MessageBox.Show("Connected!");
}
else
{
MessageBox.Show("Fail!");
}
}

SignalR Self Hosted Server 500 Error

I have recently taken an interest in SignalR but have yet to produce a working server, no matter how simple.
I have followed the GitHub Self Host documentation but I receive a nasty 500 Error.
The code I use is the following (basically the GitHub code):
class Program
{
static void Main(string[] args)
{
string host = "http://localhost:2804";
using (WebApplication.Start<InitialConf>(host))
{
Console.WriteLine("Server started on {0}", host);
Console.ReadKey();
}
}
}
class InitialConf
{
public void Configuration(IAppBuilder appBuilder)
{
var config = new HubConfiguration
{
EnableCrossDomain = true
};
// Map to default /signalr route
appBuilder.MapHubs(config);
}
}
class fooHub : Hub
{
public void DisplayTimeOnServer()
{
Console.WriteLine(DateTime.Now.ToString());
}
}
Browsing to http://localhost:2804/signalr produces a 500 Error:
HTTP/1.1 500 Internal Server Error
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
I receive no exception / error in the application so I'm not sure why it behaves like this.
Anyone have any experiences with these issues? Or perhaps could lead me on to a better documentation on the matter?
Thank you
The problem is that your Hub Class is private.
Just change that to public.
public class fooHub : Hub
{
public void DisplayTimeOnServer()
{
Console.WriteLine(DateTime.Now.ToString());
}
}
Did you try to debug on the server?
And you are missing a function/definition in you Hub to inform your clients:
Clients.All.addMessage(message);
Other that that I suggest that you check the following resources:
Home page of SignalR - tutorial: http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr
Scott's intro: http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx
It seems there is any issue with setting up a route for your connection. After your application is running you should be able to go to /signalr/hubs and see the details about the hubs.

Categories

Resources