Issue
I have a Single Page Application (SPA) with AngularJS front-end (client) and a Web API back-end (server). I also use SignalR for messaging between the client and the server. Everything works fine on my development machine (with IIS Express), but when deployed to a server for testing, I get the following error when attempting to establish a connection to a hub:
Exception thrown: System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:60161 at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult) at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception) --- End of inner exception stack trace --- at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar) --- End of inner exception stack trace --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at CMR.Messaging.PublisherService.CreateRequestService.d__7.MoveNext() in C:\Users...\CreateRequestService.cs:line 143
Even though it connects successfully to the SignalR hub from the client:
The relevant part of my client side SignalR code is this (in an AnglarJS service):
// Setting up the SignalR hub
var hub = new Hub("reportHub", {
listeners: {
'newConnection': function (id) {
},
'broadcastReportProgress': function (reportProgress) {
Reports.add(reportProgress[0].clientName, reportProgress[0].folderPath, reportProgress[0].reportName, reportProgress[0].status, reportProgress[0].userName);
$rootScope.$apply();
},
'broadcastUserGenerating': function(reportProgress) {
Reports.addActiveUser(reportProgress.clientName, reportProgress.status, reportProgress.userName);
$rootScope.$apply();
}
},
methods: ['send'],
errorHandler: function(error) {
console.error(error);
},
hubDisconnected: function () {
if (hub.connection.lastError) {
hub.connection.start();
}
},
transport: 'webSockets',
logging: true,
queryParams: { userName: authService.authentication.userName },
rootPath: 'http://localhost:60161/signalr'
});
The error occurs in the following code snippet, which is in a Window Service attempting to establish a connection to the SignalR hub (the error line corresponds to 'CreateRequestService.cs:line 143' in the error message above):
try
{
IList<ReportProgress> generationProgress = new List<ReportProgress>();
generationProgress.Add(new ReportProgress
{
ClientName = clientName,
FolderPath = response.FolderPath,
ReportName = response.Response,
Status = "InProgress",
UserName = response.UserName
});
var hubConnection = new HubConnection("http://localhost:60161/signalr", false);
IHubProxy reportHubProxy = hubConnection.CreateHubProxy("ReportHub");
**await hubConnection.Start(); --> ERROR OCCURS HERE**
await reportHubProxy.Invoke("SendReportProgress", generationProgress);
await reportHubProxy.Invoke("SendUserGenerating", generationProgress[0]);
}
catch (Exception ex)
{
throw new Exception(nameof(this.GetType) + " ****Exception**** ", ex);
}
The SignalR hub lives in my Web API project:
And here are the project properties for the Web API project. This is where the port number 60161 is set. This number is different from the port on which my SPA runs because of cross domain compatibility:
Any idea why this is happening?
Solution
So after much debugging, I finally found what the problem was. There were, in fact, two different issues at play here. First, since the code was deployed to a test server, "localhost" should not be used anywhere. Instead, the URL of the test server with a suffix 'signalr' should be used, i.e. something like 'http://testserver.companyname.com/signalr'. Second, in my client-side SignalR hub code I had the following line:
transport: 'webSockets'
That was causing a problem because on our test server Web Sockets were not enabled and therefore there was no transport to use. Once I commented out that line of code, it started working, but it was using Server Side Events (SSE) for transport, as Web Sockets were unavailable. After we went to IIS and installed and enabled them, it started using Web Sockets instead of SSE. So there you have it, the solution to that tricky problem. Hopefully this will help someone else so they don't have to spend the (about) 2 days I did to figure it out.
Answered By - lukegf
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.