Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR 2.0 change Json Serializer to support derived type objects

Please note that I'm explicitly referencing SignalR 2.0 here ... I've seen some (nasty) approaches for this with SignalR 1.1/1.2 ... but none for 2.0 yet.

Has anyone had any success with changing the SignalR 2.0 default json serializer to enable the sending of derived types? Based on what I’ve read about SignalR 2.0 this should be possible, however, I’m not having any luck and have not found a full example anywhere.

Here is how I started … any help would be appreciated.

My Startup.cs

    [assembly: OwinStartup(typeof(SignalRChat.Startup))]
    namespace SignalRChat
    {

        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                // this should allow the json serializer to maintain the object structures
                var serializer = new JsonSerializer()
                {
                    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                    TypeNameHandling = TypeNameHandling.Objects,
                    TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
                };

                // register it so that signalr can pick it up
                GlobalHost.DependencyResolver.Register(typeof(JsonSerializer), () => serializer);

                app.MapSignalR();
            }
        }
    }

Method on the Hub

    public void AddStock(Stock stock)
    {
        string stockType = stock.GetType().ToString();
        Console.WriteLine("The type of stock we got was: " + stockType);
    }

My console test app (this publishes to the hub)

    myDataHub.Invoke("AddStock", new NyseStock()
    {
        Company = "Microsoft",
        NyseSymbol = "MSFT"
    });

    myDataHub.Invoke("AddStock", new DaxStock()
    {
        Company = "Microsoft",
        DaxSymbol = "DMSFT"
    });

Just for good measure Stock.cs

    namespace Messages
    {
        public class Stock
        {
            public string Company
            {
                get;
                set;
            }
            public decimal Price
            {
                get;
                set;
            }
        }

        public class NyseStock : Stock
        {
            public string NyseSymbol
            {
                get;
                set;
            }
        }

        public class DaxStock : Stock
        {
            public string DaxSymbol
            {
                get;
                set;
            }
        }
    }

My first inclination was that I neglected to setup the serializer in the client. So I added the following after the creation of the connection but before the creation of the hub proxy :

    myConnection = new HubConnection("http://localhost:64041/");
    // Update the serializer to use our custom one
    myConnection.JsonSerializer = new JsonSerializer()
    {
         PreserveReferencesHandling = PreserveReferencesHandling.Objects,
         TypeNameHandling = TypeNameHandling.Objects,
         TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
    };

    //Make proxy to hub based on hub name on server
    myDataHub = myConnection.CreateHubProxy("DataHub");

This however just resulted in an InvalidOperationException (Data cannot be sent because the connection is in the disconnected state. Call start before sending any data.) during the myDataHub.Invoke(..) invocations.

like image 661
typhoid Avatar asked Oct 20 '13 02:10

typhoid


1 Answers

It's been a while since this question was asked. For future reference, myConnection.Start() method needs to be called after creating the proxy, like this

myConnection = new HubConnection(endpoint);

proxy = _conn.CreateHubProxy("DataHub");
proxy.On<string>("ServerEvent", ClientHandler);

myConnection.Start();

proxy.Invoke("hubMethod", ...);
like image 141
Iain Ballard Avatar answered Oct 01 '22 19:10

Iain Ballard