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
-
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))
-
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)
-
Streaming:
- Verify union types work in
IAsyncEnumerable<UnionType> streams and ChannelReader<UnionType>
-
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?
Verify that C# union types work correctly in SignalR hub methods and add test coverage
Expected behavior
Areas to investigate
JSON Hub Protocol (
JsonHubProtocol.cs):IInvocationBinder.GetParameterTypes(methodName)to resolve parameter types, then callsJsonSerializer.Deserialize(ref reader, paramType)with the exact parameter typeparamTypewill be the union type, and STJ handles union deserialization, this should work without code changesunion(int, string)) and ambiguous unions with custom classifiers (union Pet(Cat, Dog))Return value serialization:
JsonSerializer.Serialize(writer, value, type)wheretypecomes from the return typeStreaming:
IAsyncEnumerable<UnionType>streams andChannelReader<UnionType>Newtonsoft.Json protocol (
NewtonsoftJsonHubProtocol.cs):