Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize object passed as abstract class by SignalR

I have a WebAPI server that has a Hub that replies to Subscribe requests by publishing an Dictionary<long, List<SpecialParam>> object.

The list of SpecialParam contains items of type SpecialParamA & SpecialParamB which both inherit SpecialParam.

When I try to capture the publish on the client:

hubProxy.On<Dictionary<long, List<SpecialParam>>>(hubMethod, res =>
{
    DoStuff();
});

The DoStuff() method isn't called. If I change the publish return value to string, and change the proxy to receive a string value, the DoStuff() method is called. Therefore, the problem is with the deserialization of the SpecialParam Item.

I tried configuring on the server-side:

var serializer = JsonSerializer.Create();
serializer.TypeNameHandling = TypeNameHandling.All;
var hubConfig = new HubConfiguration();
hubConfig.Resolver.Register(typeof(JsonSerializer), () => serializer);
GlobalHost.DependencyResolver.Register(typeof(JsonSerializer), () => serializer);

But it didn't help.

I also tried adding to the client:

HubConnection hubConnection = new HubConnection(hubPath);
hubConnection.JsonSerializer.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;
hubProxy = hubConnection.CreateHubProxy(hubName);
hubProxy.JsonSerializer.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;

And it also didn't help.

In other solutions I found that people defined a new IParameterResolver, but it is only called when the server receives the input to the hub method, and not when the output is published from the hub.

Please help!

UPDATE

Here is what I caught with fidler:

{"$type":"Microsoft.AspNet.SignalR.Hubs.HubResponse, Microsoft.AspNet.SignalR.Core","I":"0"}

This is what the server replies to the client.

UPDATE 2

I'm still trying to figure out how to receive it already deserialized as Dictionary<long, List<SpecialParam>>.

like image 719
shlatchz Avatar asked Apr 24 '16 11:04

shlatchz


1 Answers

I solved it by setting in the service:

public static void ConfigureApp(IAppBuilder appBuilder)
{
    ...
    var service = (JsonSerializer)GlobalHost.DependencyResolver.GetService(typeof(Newtonsoft.Json.JsonSerializer));
    service.TypeNameHandling = TypeNameHandling.All;
    ...
}

and removing the expected type in the client:

hubProxy.On(hubMethod, res =>
{
    DoStuff();
});

I get the response in json form and I deserialize it with:

var serializer = new JsonSerializer();
serializer.TypeNameHandling = TypeNameHandling.All;
JObject jObject = resp as JObject;
var specialParams = jObject.ToObject<Dictionary<long, List<SpecialParam>>>(serializer);

I still don't know how to make my client receive it already deserialized.

like image 146
shlatchz Avatar answered Oct 14 '22 19:10

shlatchz