Search code examples
c#azurecorsazure-web-app-serviceasp.net-core-signalr

SignalR errors in the console even though the requests successfully completed


I have configured cross applications SignalR (I use builtin SignalR) communication (between webapp and asp.net mvc applications on different endpoints). Locally it works fine and doesn't trigger any errors or warnings in browser console.

When I deploy this application to azure, it still works fine, but I see strange errors in the browser console (just during starting UI application before any communications):

[ERROR]
* The connection to https://mywebapp.eastus-01.azurewebsites.net/NotificationHub?id=aaaaaaaaaaaaaaaaaaaa-g was interrupted while the page was loading. signalr.js:2446:31
* [2024-09-21T20:15:31.733Z] Information: Connection disconnected. signalr.js:453:30
* [2024-09-21T20:15:32.420Z] Information: SSE connected to https://mywebapp.eastus-01.azurewebsites.net/NotificationHub?id=s8Tsz4ASX_0G9QDnVp9o7g signalr.js:453:30
* [2024-09-21T20:15:33.475Z] Information: SSE connected to https://mywebapp.eastus-01.azurewebsites.net/NotificationHub?id=CJxP06m_KbrlaT59XgHqtw signalr.js:453:30
[WARNING]
* Source map error: Error: request failed with status 404
Resource URL: https://myuiapp.eastus-01.azurewebsites.net/lib/microsoft/signalr/dist/browser/signalr.js
Source Map URL: signalr.js.map
[WARNING]
* Source map error: request failed with status 404
Resource URL: https://myuiapp.eastus-01.azurewebsites.net/lib/microsoft/signalr/dist/browser/signalr.js
Source Map URL: signalr.js.map

As I said, it doesn't affect logic, so notifications from the api are received correctly, but I wonder what these errors/warnings are about.

Configuration on API side (but as I said, this error is triggered during starting application before any notification steps involved):

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: "CorsSignalr", policyBuilder =>
        policyBuilder
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials()
            .SetIsOriginAllowed(hostName => true));
});

app.UseCors("CorsSignalr");
app.MapHub<NotificationHub>("/NotificationHub");

Sending request (not called during starting application):

       var userGroupName = "name";
       var group = _notificationHub.Clients.Group(userGroupName);

       await group.SendAsync(
           method: javascriptMethodName,
           arg1: arg1,
           ...
           userName);

on UI side there is only js configuration (also no cors or other signalr related configuration):

let signalRHostName= document.getElementById("API_HOST_ADDRESS").value
var connection = new signalR.HubConnectionBuilder()
    .withUrl(signalRHostName.concat("/NotificationHub"))
    .withAutomaticReconnect()
    .build();

on the azure web app side, I see signalr.js presents in wwwroot/wwwroot folder:

C:\home\site\wwwroot\wwwroot\lib\microsoft\signalr\dist\browser>ls
signalr.js
signalr.min.js

so, how to troubleshoot this issue?

UPDATE1: thanks @LexLi, this looks like a good idea to proceed, but I'm not sure yet how to do it correctly. I changed code in 2 places:

added transport on js side:

    var connection = new signalR.HubConnectionBuilder()
    .withUrl(signalRHostName.concat("/NotificationHub"), {
        transport: signalR.HttpTransportType.ServerSentEvents
    })
    .withAutomaticReconnect()
    .build();

and configured transport on API side in this way:

app.MapHub<NotificationHub>("/NotificationHub", (options) => 
{
    options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.ServerSentEvents;
});

No more changes applied. If it's enough to configure SSE, the output is the same with 100% the same sequence of the messages (including info/warnings/errors) in the console

UPDATE2:

I call creating connection in customSignalR.js right after footer in _Layout.cshtml:

 <footer class="border-top footer text-muted">
 </footer>
 <script src="~/lib/jquery/dist/jquery.min.js"></script>
 <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
 <script src="~/lib/microsoft/signalr/dist/browser/signalr.js"></script>
 <script src="~/js/customSignalR.js"></script>
 @await RenderSectionAsync("Scripts", required: false)

where inside customSignalR.js I create new signalR.HubConnectionBuilder right in the beginning of the file.

UPDATE3:

After enabling debug logs on js side, during starting application I see:

    The connection to https://myapi.eastus-01.azurewebsites.net/NotificationHub?id=bbbb was interrupted while the page was loading. signalr.js:2446:31
    [2024-09-23T05:23:53.574Z] Debug: HttpConnection.stopConnection(undefined) called while in state Connected. signalr.js:457:30
    [2024-09-23T05:23:53.575Z] Information: Connection disconnected. signalr.js:453:30
    [2024-09-23T05:23:53.575Z] Debug: HubConnection.connectionClosed(undefined) called while in state Connected. signalr.js:457:30
    [2024-09-23T05:23:53.575Z] Information: Connection reconnecting. signalr.js:453:30
    [2024-09-23T05:23:53.575Z] Information: Reconnect attempt number 1 will start in 0 ms. signalr.js:453:30
    [2024-09-23T05:23:53.575Z] Debug: Starting connection with transfer format 'Text'. signalr.js:457:30
    [2024-09-23T05:23:53.575Z] Debug: Sending negotiation request: https://myapi.eastus-01.azurewebsites.net/NotificationHub/negotiate?negotiateVersion=1. signalr.js:457:30
    [2024-09-23T05:23:55.002Z] Debug: Starting HubConnection. signalr.js:457:30
    [2024-09-23T05:23:55.004Z] Debug: Starting connection with transfer format 'Text'. signalr.js:457:30
    [2024-09-23T05:23:55.004Z] Debug: Sending negotiation request: https://myapi.eastus-01.azurewebsites.net/NotificationHub/negotiate?negotiateVersion=1. signalr.js:457:30
    [2024-09-23T05:23:55.371Z] Debug: Selecting transport 'ServerSentEvents'. signalr.js:457:30
    [2024-09-23T05:23:55.556Z] Information: SSE connected to https://myapi.eastus-01.azurewebsites.net/NotificationHub?id=aaaa signalr.js:453:30
    [2024-09-23T05:23:55.556Z] Debug: The HttpConnection connected successfully. signalr.js:457:30
    [2024-09-23T05:23:55.556Z] Debug: Sending handshake request. signalr.js:457:30
    [WARNING]
    Source map error: Error: request failed with status 404
    Resource URL: https://myuiapp.eastus-01.azurewebsites.net/lib/microsoft/signalr/dist/browser/signalr.js
    Source Map URL: signalr.js.map

    [2024-09-23T05:23:56.082Z] Information: Using HubProtocol 'json'. signalr.js:453:30
    [2024-09-23T05:23:56.083Z] Debug: Server handshake complete. signalr.js:457:30
    [2024-09-23T05:23:56.291Z] Debug: HubConnection connected successfully

sounds like websocket protocol can't be used for some reason and SSE does all work as fallback (not sure why enabling SSE directly doesn't help though), any ideas how to enable it on azure app services?

UPDATE4: thanks @JasonPan, apparently websockets are not enabled by default in azure app services, after enabling it, all errors were gone, the only remaining question is a single warning:

Source map error: Error: request failed with status 404
Resource URL: https://myuiapp.eastus-01.azurewebsites.net/lib/microsoft/signalr/dist/browser/signalr.js
Source Map URL: signalr.js.map 

this file exists on the azure side, not sure why I see this 404 error/warning?


Solution

  • From the signalr client-side logs, we can find the signalr connection works via SSE. It's means it's not the code issue.

    Then we need to enable webscoket feature in platform, for azure app service, we can configure it in azure portal like below.

    enter image description here

    And for Source map error: Error: request failed with status 404.

    This is a browser feature and expected when you open the browser debugger and don't have the .map file.

    enter image description here