Skip to content

SignalR: Verify union types work as hub method parameters and return values #66547

@DeagleGross

Description

@DeagleGross

Verify that C# union types work correctly in SignalR hub methods and add test coverage

Expected behavior

union ChatMessage(TextMessage, ImageMessage, SystemNotification);

public class ChatHub : Hub
{
    // Union as parameter — client sends JSON, STJ deserializes to union
    public async Task SendMessage(ChatMessage message)
    {
        await Clients.All.SendAsync("ReceiveMessage", message);
    }

    // Union as return value — STJ serializes the active case
    public ChatMessage GetLastMessage()
    {
        return new ChatMessage(new TextMessage { Text = "Hello" });
    }
}

Areas to investigate

  1. JSON Hub Protocol (JsonHubProtocol.cs):

    • Uses IInvocationBinder.GetParameterTypes(methodName) to resolve parameter types, then calls JsonSerializer.Deserialize(ref reader, paramType) with the exact parameter type
    • Since paramType will be the union type, and STJ handles union deserialization, this should work without code changes
    • Verify with both unambiguous unions (union(int, string)) and ambiguous unions with custom classifiers (union Pet(Cat, Dog))
  2. Return value serialization:

    • Hub return values are serialized via JsonSerializer.Serialize(writer, value, type) where type comes from the return type
    • Verify the union case value is serialized correctly (not the union wrapper)
  3. Streaming:

    • Verify union types work in IAsyncEnumerable<UnionType> streams and ChannelReader<UnionType>
  4. Newtonsoft.Json protocol (NewtonsoftJsonHubProtocol.cs):

    • Union support will NOT work with Newtonsoft.Json unless Newtonsoft adds union support
    • Verify graceful error handling — what happens if a union type is used with the Newtonsoft protocol?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions