SignalR: Empty /negotiate response with HTTP 200 when .net 8 app hosted on IIS from Microsoft.AspNetCore.Connections.Abstractions version 9.x onwards
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
We recently updated one nuget package (Microsoft.AspNetCore.SignalR.Protocols.MessagePack) on our SignalR enabled ASP.NET Core app to the latest version 9.0.10, and suddenly connections could not be made anymore from our .net48 client application.
Upon investigation by looking at the traffic via Fiddler, we found that on any Hub's /negotiate call, the server would respond with a HTTP 200 OK message - but with a completely empty body, which is invalid according to the SignalR protocol definition. Our request:
`POST http://localhost:5000/UserManagement/Login/negotiate?negotiateVersion=1 HTTP/1.1
Accept: */*
User-Agent: Microsoft SignalR/9.0 (9.0.10+5bae930797f60d2d04f3b1df6a33eaca85fc5f28; Windows NT; .NET; .NET Framework 4.8.9310.0)
X-Requested-With: XMLHttpRequest
Host: localhost:5000
Content-Length: 0
Connection: Keep-Alive
`
Response:
`HTTP/1.1 200 OK
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Thu, 23 Oct 2025 11:01:21 GMT
Content-Length: 0
`
Further investigation revealed that this ONLY happens when hosting the App on IIS (in-process hosting) and the culprit seems to be the package Microsoft.AspNetCore.Connections.Abstractions - installing it, or any package that depends on it, leads to the error.
- On Kestrel it works fine, always
- On IIS it works fine with the above package on the latest 8.x version (8.0.21)
- Updating the above package to 9.0.0 or above leads to the wrong behavior above
- When we switch our app to .net 9, it works fine again
### Expected Behavior
Hosting on IIS or kestrel should not matter; in both cases, /negotiate should return a negotiation response along with the HTTP 200.
### Steps To Reproduce
https://github.com/Shanayara/aspnetcore-signalr-net8-connection-abstractions-9-issue
### Exceptions (if any)
When using the C# .net 4.8 SignalR client:
System.IO.InvalidDataException: Invalid negotiation response received. ---> System.Text.Json.JsonReaderException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. LineNumber: 0 | BytePositionInLine: 0..
bei System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
bei System.Text.Json.Utf8JsonReader.Read()
bei Microsoft.AspNetCore.Internal.SystemTextJsonExtensions.CheckRead(Utf8JsonReader& reader)
bei Microsoft.AspNetCore.Http.Connections.NegotiateProtocol.ParseResponse(ReadOnlySpan`1 content)
--- Ende der internen Ausnahmestapelüberwachung ---
bei Microsoft.AspNetCore.Http.Connections.NegotiateProtocol.ParseResponse(ReadOnlySpan`1 content)
bei Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.d__45.MoveNext()`
### .NET Version
9.0.306
### Anything else?
dotnet --info
.NET SDK:
Version: 9.0.306
Commit: cc9947ca66
Workload version: 9.0.300-manifests.abe91478
MSBuild version: 17.14.28+09c1be848
Laufzeitumgebung:
OS Name: Windows
OS Version: 10.0.26100
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\9.0.306\
Installierte .NET-Workloads:
Es sind keine installierten Workloads zum Anzeigen vorhanden.
Konfiguriert für die Verwendung loose manifests beim Installieren neuer Manifeste.
Host:
Version: 9.0.10
Architecture: x64
Commit: e1f19886fe
.NET SDKs installed:
8.0.415 [C:\Program Files\dotnet\sdk]
9.0.306 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.21 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
Contributor guide
Research direction
Start with the linked reproduction project and compare the /negotiate response under IIS in-process and Kestrel using Microsoft.AspNetCore.Connections.Abstractions 8.0.21 versus 9.0.x. Confirm the fix by verifying that the .NET 8 IIS deployment returns a valid SignalR negotiation JSON response with HTTP 200.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100