I am trying to send a list of objects to my signalr clients, but the framework seems to ignore the json serializer and uses the ToString
method instead. This only happens if it's a List<object>
, it can handle a regular object
just fine.
A somewhat contrived simplified example:
public abstract class Animal {}
public class Dog : Animal {
public bool GoodBoy { get; set; }
public override string ToString() {
return "hello from dog";
}
}
public class Cat : Animal {
public bool Hungry { get; set; } // only cats can be hungry, dont think too much about it
}
// ... class MyHub : Hub { ...
// Input is: type = typeof(Dog) and animals is a list of 1 dog
public void SendChanges(Type type, List<Animal> animals) {
// Just serializing the animals without casting them gives incorrect objects
Console.WriteLine(JsonSerializer.Serialize(animals)); // Prints [{}]
// So we have to cast to the input type
var animalsAsType = animals.Select(a => Convert.ChangeType(a, type).ToList();
Console.WriteLine(JsonSerializer.Serialize(animalsAsType)); // Prints [{"GoodBoy":true}]
// However, ...
Clients.Others.SendAsync($"On{type.Name}Changed", animalsAsType); // Clients receive ["hello from dog"]
}
What am I doing wrong here? I suspect there's something wrong in my linq Select
, but I am unsure how to cast an Animal
to type
(with it throwing a ClassCastException
if the animal instance is not actually the type we're trying to cast to) that does not use Convert.ChangeType
.
Note: Due to technical limitations in my real code I do require that the signature of SendChanges(Type type, List<Animal> animals)
doesn't change.
I found the issue: Turns out that I forgot that I had registered a custom json converter that used ToString
. Once I followed this solution everything worked perfectly.