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.