{"record":{"id":"7e4e056612d1ec15","repo":"OrchardCMS/OrchardCore","slug":"detected-a-connection-attempt-to-an-asp-net-signalr-server","errorCode":null,"errorMessage":"Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.","messagePattern":"Detected a connection attempt to an ASP\\.NET SignalR Server\\. This client only supports connecting to an ASP\\.NET Core SignalR Server\\. See https://aka\\.ms/signalr-core-differences for details\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.SignalR/wwwroot/Scripts/signalr.js","lineNumber":2850,"sourceCode":"                }\n                else {\n                    throw new Error(\"Negotiation can only be skipped when using the WebSocket transport directly.\");\n                }\n            }\n            else {\n                let negotiateResponse = null;\n                let redirects = 0;\n                do {\n                    negotiateResponse = await this._getNegotiationResponse(url);\n                    // the user tries to stop the connection when it is being started\n                    if (this._connectionState === \"Disconnecting\" /* ConnectionState.Disconnecting */ || this._connectionState === \"Disconnected\" /* ConnectionState.Disconnected */) {\n                        throw new AbortError(\"The connection was stopped during negotiation.\");\n                    }\n                    if (negotiateResponse.error) {\n                        throw new Error(negotiateResponse.error);\n                    }\n                    if (negotiateResponse.ProtocolVersion) {\n                        throw new Error(\"Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.\");\n                    }\n                    if (negotiateResponse.url) {\n                        url = negotiateResponse.url;\n                    }\n                    if (negotiateResponse.accessToken) {\n                        // Replace the current access token factory with one that uses\n                        // the returned access token\n                        const accessToken = negotiateResponse.accessToken;\n                        this._accessTokenFactory = () => accessToken;\n                        // set the factory to undefined so the AccessTokenHttpClient won't retry with the same token, since we know it won't change until a connection restart\n                        this._httpClient._accessToken = accessToken;\n                        this._httpClient._accessTokenFactory = undefined;\n                    }\n                    redirects++;\n                } while (negotiateResponse.url && redirects < MAX_REDIRECTS);\n                if (redirects === MAX_REDIRECTS && negotiateResponse.url) {\n                    throw new Error(\"Negotiate redirection limit exceeded.\");\n                }","sourceCodeStart":2832,"sourceCodeEnd":2868,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.SignalR/wwwroot/Scripts/signalr.js#L2832-L2868","documentation":"During negotiation the client checks negotiateResponse.ProtocolVersion; a presence of this field indicates the endpoint is a legacy ASP.NET (non-Core) SignalR server, whose protocol is incompatible with the @microsoft/signalr client. The client throws this descriptive error instead of failing later with cryptic protocol errors.","triggerScenarios":"Pointing the JS client at an ASP.NET (Framework) SignalR endpoint /signalr/negotiate that returns a ProtocolVersion in its negotiate payload; mixing Microsoft.AspNet.SignalR server code with the @microsoft/signalr (Core) client.","commonSituations":"Migrating an old ASP.NET app to .NET Core and keeping the legacy hub URL; proxying '/signalr' to a legacy backend; upgrading the client package (@aspnet/signalr -> @microsoft/signalr) while the server is still ASP.NET SignalR 2.x.","solutions":["Migrate the server to ASP.NET Core SignalR (Microsoft.AspNetCore.SignalR) and use its hub endpoint.","If the server must stay on ASP.NET SignalR 2.x, use the matching legacy client (jquery.signalR / Microsoft.AspNet.SignalR JS client).","Verify the negotiate response: a Core server returns connectionId/availableTransports without ProtocolVersion.","Check for reverse-proxy rewrites routing /signalr to a legacy host unintentionally."],"exampleFix":"// before (legacy server + Core client)\nconst connection = new signalR.HubConnectionBuilder().withUrl(\"http://legacy-server/signalr\").build();\n// after (upgrade server to ASP.NET Core)\n// Server: app.MapHub<MyHub>(\"/hub\") with Microsoft.AspNetCore.SignalR\nconst connection = new signalR.HubConnectionBuilder().withUrl(\"https://core-app/hub\").build();","handlingStrategy":"validation","validationCode":"// client-side preflight\nasync function isAspNetCoreHub(url) {\n  const res = await fetch(`${url}/negotiate`, { method: \"POST\" });\n  const body = await res.json();\n  return body.ProtocolVersion === undefined; // Core servers omit ProtocolVersion\n}","typeGuard":"function isCoreNegotiateResponse(body) {\n  return body && body.connectionId !== undefined && body.ProtocolVersion === undefined;\n}","tryCatchPattern":"try {\n  await connection.start();\n} catch (err) {\n  if (err.message.includes(\"ASP.NET SignalR Server\")) {\n    console.error(\"Target is legacy ASP.NET SignalR — use matching client/server versions\");\n  } else { throw err; }\n}","preventionTips":["Verify server/client stack parity: @microsoft/signalr only speaks to ASP.NET Core SignalR.","Check the negotiate payload during migration projects.","Audit reverse-proxy routes so /signalr is not left pointing at a legacy host.","Pin hub URLs per environment in configuration to avoid stale endpoints."],"tags":["signalr","version-incompatibility","protocol-mismatch","migration"],"backgroundTag":"version-incompatible","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}