Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR SSE handshake fails

Hosting a ASP.Net Core 2.1 webapi and an Angular 6 webapp on "Windows Server 2008 R2" under the same domain name but different ports (:81 and :80 respectively); not contained within the same folder.

According to this article, SSE is the (standard) fallback when Websockets are unavailable, which is expected since the server doesn't support Websockets as they were introduced in IIS 8.0 (server is IIS 7.5)

In development everything works perfectly. However, after publishing, the browser console reports the following after 15 seconds (suspiciously the default "HandshakeTimeout" time).

> Information: SSE connected to http://my.website.com:81/notify?id=kaSkcGUjcZD4ylJAC7B70A
> Error: Connection disconnected with error 'Error: Server returned handshake error: Handshake was canceled.'.
> Error: Not Found

The Startup.cs is currently setup as follows:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR();
    services.AddMemoryCache();
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    services.AddCors(o => {
        o.AddPolicy("Limited", builder => builder
            .WithOrigins("http://my.website.com") // .AllowAnyOrigin() also tested and worked
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials()
        );
    });
    services.AddDbContext<DatabaseContext>(options => {
        options.UseSqlServer(Configuration.GetConnectionString("Database"));
    });
}

public void Configure(
    IApplicationBuilder app,
    IHostingEnvironment env,
    IServiceProvider serviceProvider)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseCors("Limited");
    app.UseHttpsRedirection();
    app.UseMvc();
    app.UseSignalR(routes => routes.MapHub<NotifyHub>("/notify"));
}

With the SignalR Hub being almost empty (event pushing is handled elsewhere):

public class NotifyHub : Hub
{
    public override async Task OnConnectedAsync()
    {
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        await base.OnDisconnectedAsync(exception);
    }
}

The Angular service is setup as follows:

import { Injectable } from '@angular/core';
import { HubConnection } from '@aspnet/signalr';
import * as signalR from '@aspnet/signalr';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class RefreshService {
  private connection: HubConnection;
  public timestamp = new Subject<string>();

  constructor(private zone: NgZone) {
    this.connection = new signalR.HubConnectionBuilder()
      .withUrl(http://my.website.com:81/notify)
      .build();

    this.connection
      .start()
      .then(() => {
        this.connection.on('Message', data => {
          // Do Work
        });
      })
      .catch(err => console.error(err.toString()));
  }
}

All NuGet packages are up to date (v2.1.1 for everything but Microsoft.NETCore.App which is v2.1.0) and using v1.0.2 (the latest) ASP.NET SignalR NPM package -- so the server- and client-side SignalRs are the same.

Using a static IP address I was able to get the app to connect to a locally published API (but running IIS 10.0).

Is there something I am missing? A lot of the technologies are pretty new, but I don't yet want to assume there's something wrong with them.

like image 868
H3katonkheir Avatar asked Aug 13 '18 10:08

H3katonkheir


People also ask

What causes SignalR to disconnect?

If a server does not become available within the disconnect timeout period, the SignalR connection ends. In this scenario, the Closed event ( disconnected in JavaScript clients) is raised on the client but OnDisconnected is never called on the server.

Does SignalR require sticky session?

Sticky SessionsSignalR requires that all HTTP requests for a specific connection be handled by the same server process. When SignalR is running on a server farm (multiple servers), "sticky sessions" must be used. "Sticky sessions" are also called session affinity by some load balancers.


1 Answers

In case someone is still facing this issue, I solved it by configuring IIS 8.0 WebSocket Protocol Support on IIS.

Microsoft documentation

like image 55
LNyarla Avatar answered Nov 11 '22 16:11

LNyarla