Search code examples
c#asp.net-coreasp.net-core-signalr

signalR + IIS 404 negotiate angular4 client (1.0.0-preview1-final)


I am using ASP.NET Core 2.0 with Microsoft.AspNetCore.SignalR (1.0.0-preview1-final).

I have an issue deploying my application using IIS (with Kestrel). When I run the server in localhost using IIS Express, everything works as expected, but when I try to run on IIS (Windows server or local host windows 7), the negotiate call fail to 404

POST http://localhost/notification/negotiate 404 (Not Found)

404 response content

I tried configuring IIS with different topics found online, but no success. (<modules runAllManagedModulesForAllRequests="true" />, extension-less url with https://support.microsoft.com/en-gb/help/980368/a-update-is-available-that-enables-certain-iis-7-0-or-iis-7-5-handlers)

But I am still pretty sure the issue is related to my IIS configuration since the entire project works fine on IIS Express...

This is the web.config file used on the test server (I removed the different debug tries, since it was not working...)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath=".\MyProject.Web.App.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
  </system.webServer>
</configuration>
<!--ProjectGuid: {{some GUID here}}-->

Part of the code used in Configure method

        app.UseSignalR(route =>
        {
            route.MapHub<NotificationHub>("/notification");
        });
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });

Part of the code used in ConfigureServices method

        services.AddMvc()
        services.AddSignalR();
        services.AddSession();

Angular application code

constructor() {
    /** ... **/

    this.hubConnection = new HubConnection('/notification', {
        transport: TransportType.LongPolling
    });

    this.hubConnection.on('Update', (data: string) => {
        let res = new DefaultNotificationInfo(data);
        /** ... **/
    });

    this.hubConnection.start()
        .then(() => {
            this.join().then(next => {
                // nothing to do on join, the socket is running
            }).catch(error => {
                console.error(error)
            });
        })
        .catch(err => {
            console.error(err)
        });
}

private join(): Promise<any> {
    return this.hubConnection.invoke('Join');
}

Versions informations :

IIS : 7.5

APP net package.json:

        {
        /** ... **/
        "@aspnet/signalr": "^1.0.0-preview1-update1",
        "@aspnet/signalr-client": "^1.0.0-alpha2-final",
        /** ... **/
        }

API asp net nuget version : (1.0.0-preview1-final)


After reading https://blogs.msdn.microsoft.com/webdev/2017/09/14/announcing-signalr-for-asp-net-core-2-0/ and https://blogs.msdn.microsoft.com/webdev/2018/02/27/asp-net-core-2-1-0-preview1-getting-started-with-signalr/, I am pretty sure I've covered everything from their tutorial/quick-start

Is there something I missed?


Update 1

After finding this : https://stackoverflow.com/a/43014264/3198096 I tried to enable the LoadUserProfile property of my ApplicationPool using this link https://blogs.msdn.microsoft.com/vijaysk/2009/03/08/iis-7-tip-3-you-can-now-load-the-user-profile-of-the-application-pool-identity/

But this is still failing to 404.

I also tried to "Attach to process" on my application to see if there was any logs corresponding to my Hub or to the /negotiate url, but there was none.

(also added a screenshot of the 404 result)

Update 2

This is an extract of package.config from the Web.App

package.config file extract

Update 3

This is the configuration of the server hosting the applications. You can see 3 different website. All of them have almost the same configuration. (Just the port changing, which define 3 different test environment access)

IIS server Config

And this is the basic localhost developer IIS, which I guess i generated by Visual Studio.

IIS local Config


Solution

  • There is a very similar issue on github. If the website isn't hosted on the root (ex. by using virtual directories or something similar), SignalR will use the wrong URL at the moment of writing. For example, if your "website-root" is on

    http://YOUR_URL/test/index.html
    

    you would have to use

    this.hubConnection = new HubConnection('/test/notification', {
        transport: TransportType.LongPolling,
        logger: signalR.LogLevel.Trace
    });
    

    If the above doesn't work, I suggest you to add logging to your client app (as shown above) and your server. This will show you what exactly goes wrong.