Skip to content

[3.1.x - SignalR] Duplex Stream using IAsyncEnumerable fail to Bind argument while it works with ChannelReader, or on 5.x with both #25164

@tebeco

Description

@tebeco

Describe the bug

This bug seems to occur when running on 3.1.x
My initial attempt to migrate the repro code on this repository was on main branch and I think I could not reproduce, this might require double check
I pushed 2 branches with code "relatively up to date" on releases/3.1 and the old main while it was BEFORE the move to 6.0 here

When trying to do a sort of Duplex streaming using IAsyncEnumerable + HubConnection inside a Hub class, the HubInvocationBindier<THub> does not seems to detect that the targeted "second" Hub as a parameter (the IAsyncEnumerable).
The failure is happening when "planets are aligned" :

  • All things described later use IAsyncEnumerable (not ChannelReader)
  • EnableDetailedError is set to true
  • the runtime is the LTS 3.1.x
  • The streaming is happening within a Hub already streaming
  • The "action" invoqued is both:
    • accepting Stream from Client
    • returning Stream to Client
    • This "action" is also using a HubConnection that
      • Stream to another Hub
      • accept Stream from that other Hub

AppA is like a dotnet new worker -n AppA
AppB is like a dotnet new webapi -n AppB
AppC is like a dotnet new webapi -n AppC

A stream is supposed to be generated on AppA => [1, 2, 3, 4]
It's streamed to AppB
AppB also has a HubConnection client streaming to AppC
For debug purpose I added some helper to "Log" / "Multiply" / "Enumerate Back" the stream values by 10x

AppA
     ==> AppB
               ==> AppC
         AppB <==
AppA <==

To Reproduce

git clone --recursive https://github.com/tebeco/aspnetcore repro31
cd repro31
git checkout -b repro-bug-iae-signalr-duplex-on-31 origin/repro-bug-iae-signalr-duplex-on-31
./restore.cmd
./build.cmd
cd ./src/SignalR
./startvs.cmd

Change startup to be multiple project :
image

  • These sample have both implementation for IAsyncEnumerable and ChannelReader
  • Make sure to check the "streaming startup code" in the Worker BackgroundService :
  • //*/ will toggle IAsyncEnumerable
  • /*/ will toggle ChannelReader
    image
    image

Press F5
It should throw a System.IO.InvalidDataException 'Invocation provides 1 argument(s) but target expects 0.'

For the code targetting 5.0:

git clone --recursive https://github.com/tebeco/aspnetcore repro50
cd repro50
git checkout -b no-repro-on-50 origin/no-repro-on-50
./restore.cmd
./build.cmd
cd ./src/SignalR
./startvs.cmd

Exceptions (if any)

System.IO.InvalidDataException: 'Invocation provides 1 argument(s) but target expects 0.'

StackTrace :

Microsoft.AspNetCore.SignalR.Protocols.Json.dll!Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.BindTypes(ref System.Text.Json.Utf8JsonReader reader, System.Collections.Generic.IReadOnlyList<System.Type> paramTypes) Line 731	C#
Microsoft.AspNetCore.SignalR.Protocols.Json.dll!Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.ParseMessage(System.Buffers.ReadOnlySequence<byte> input, Microsoft.AspNetCore.SignalR.IInvocationBinder binder) Line 270	C#
Microsoft.AspNetCore.SignalR.Protocols.Json.dll!Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.TryParseMessage(ref System.Buffers.ReadOnlySequence<byte> input, Microsoft.AspNetCore.SignalR.IInvocationBinder binder, out Microsoft.AspNetCore.SignalR.Protocol.HubMessage message) Line 91	C#
Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.HubConnectionHandler<AppC.Hubs.AppCHub>.DispatchMessagesAsync(Microsoft.AspNetCore.SignalR.HubConnectionContext connection) Line 269	C#
[Resuming Async Method]	
[Async Call Stack]	
[Async] Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.HubConnectionHandler<AppC.Hubs.AppCHub>.RunHubAsync(Microsoft.AspNetCore.SignalR.HubConnectionContext connection) Line 147	C#
[Async] Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.HubConnectionHandler<AppC.Hubs.AppCHub>.OnConnectedAsync(Microsoft.AspNetCore.Connections.ConnectionContext connection) Line 119	C#
[Async] Microsoft.AspNetCore.Http.Connections.dll!Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionContext.ExecuteApplication(Microsoft.AspNetCore.Connections.ConnectionDelegate connectionDelegate) Line 534	C#
[Async] System.Private.CoreLib.dll!System.Threading.Tasks.TaskFactory.ContinueWhenAny	Unknown
[Async] Microsoft.AspNetCore.Http.Connections.dll!Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher.DoPersistentConnection(Microsoft.AspNetCore.Connections.ConnectionDelegate connectionDelegate, Microsoft.AspNetCore.Http.Connections.Internal.Transports.IHttpTransport transport, Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionContext connection) Line 272	C#
[Async] Microsoft.AspNetCore.Http.Connections.dll!Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher.ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Connections.ConnectionDelegate connectionDelegate, Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions options, Microsoft.AspNetCore.Http.Connections.Internal.ConnectionLogScope logScope) Line 173	C#
[Async] Microsoft.AspNetCore.Http.Connections.dll!Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher.ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions options, Microsoft.AspNetCore.Connections.ConnectionDelegate connectionDelegate) Line 82	C#
[Async] Microsoft.AspNetCore.Routing.dll!Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke.__AwaitRequestTask|6_0(Microsoft.AspNetCore.Http.Endpoint endpoint, System.Threading.Tasks.Task requestTask, Microsoft.Extensions.Logging.ILogger logger) Line 80	C#
[Async] Microsoft.AspNetCore.Server.Kestrel.Core.dll!Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests<Microsoft.AspNetCore.Hosting.HostingApplication.Context>(Microsoft.AspNetCore.Hosting.Server.IHttpApplication<Microsoft.AspNetCore.Hosting.HostingApplication.Context> application) Line 623	C#
[Async] Microsoft.AspNetCore.Server.Kestrel.Core.dll!Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync<Microsoft.AspNetCore.Hosting.HostingApplication.Context>(Microsoft.AspNetCore.Hosting.Server.IHttpApplication<Microsoft.AspNetCore.Hosting.HostingApplication.Context> application) Line 534	C#
[Async] Microsoft.AspNetCore.Server.Kestrel.Core.dll!Microsoft.AspNetCore.Server.Kestrel.Core.Internal.HttpConnection.ProcessRequestsAsync<Microsoft.AspNetCore.Hosting.HostingApplication.Context>(Microsoft.AspNetCore.Hosting.Server.IHttpApplication<Microsoft.AspNetCore.Hosting.HostingApplication.Context> httpApplication) Line 101	C#
[Async] Microsoft.AspNetCore.Server.Kestrel.Core.dll!Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware.InnerOnConnectionAsync(Microsoft.AspNetCore.Connections.ConnectionContext context) Line 260	C#
[Async] Microsoft.AspNetCore.Server.Kestrel.Core.dll!Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.KestrelConnection.ExecuteAsync() Line 197	C#

Further technical details

  • ASP.NET Core version : 3.1.7 / 3.1.8 (to be released ?)
  • Include the output of dotnet --info :
 C:\dev\github\tebeco\aspnetcore\src\SignalR   repro-bug-iae-signalr-duplex-on-31 ≣ +0 ~1 -0 ! 
[15:24]❯ dotnet --info

Host (useful for support):
  Version: 5.0.0-preview.7.20364.11
  Commit:  53976d38b1

.NET SDKs installed:
  2.1.808 [C:\Program Files\dotnet\sdk]
  2.2.402 [C:\Program Files\dotnet\sdk]
  3.1.202 [C:\Program Files\dotnet\sdk]
  3.1.302 [C:\Program Files\dotnet\sdk]
  3.1.400 [C:\Program Files\dotnet\sdk]
  3.1.401 [C:\Program Files\dotnet\sdk]
  5.0.100-preview.7.20366.6 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.0-preview.7.20365.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.0-preview.7.20364.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.0-preview.7.20366.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download
  • The IDE (VS / VS Code/ VS4Mac) you're running on, and it's version
  • VsCode Insider
  • Vs2019 Enterprise Preview 16.8 Preview 1

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-signalrIncludes: SignalR clients and servers

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions