Archives / 2020 / November
  • Tiny Difference, Big Consequences Reloaded: SignalR in .NET Core 3.1 vs. .NET 5

    In a past blog post I wrote about a surprising change I encountered during the migration of a .NET Core 2.2 application to .NET Core 3.0. I have just migrated that same application to .NET 5 and guess what, I stumbled across another “tiny difference with big consequences”.

    The situation: I have a WPF desktop client that communicates with an ASP.NET Core server that in turn communicates with a small TypeScript browser application. I use Web API for accessing files and meta data, and SignalR to call remote functions.

    After the migration I ran the application and things were working fine – until a certain point, where I received the following exception in a call of SignalR’s HubConnection.InvokeCoreAsync() (actual function name replaced with “doSomething”):

       Message=Failed to invoke 'doSomething' due to an error on the server.

    On the server side, my own code was not even called.

    It took me a while to notice that one of the parameters of the function had the type of a class with a specific constellation of constructors:

    • A public constructor with parameters
    • A private default constructor.

    It turned out while SignalR in .NET Core 3.1 has no problem (de)serializing an instance of a class with a private default constructor, SignalR in .NET 5 does. So simply removing that constructor fixed the problem. In terms forcing the usage of the other constructor when explicitly creating objects of that type, nothing changed; I did not need a private default constructor for that.

    P.S. Do not ask me why I had a private default constructor in the first place. But the project is a couple of years old now, and things like this do happen.