microsoft / vs-streamjsonrpc

The StreamJsonRpc library offers JSON-RPC 2.0 over any .NET Stream, WebSocket, or Pipe. With bonus support for request cancellation, client proxy generation, and more.
Other
730 stars 149 forks source link

Unhandled Exception: Newtonsoft.Json.JsonSerializationException: Unable to deserialize JsonRpcMessage. #1060

Closed famasf1 closed 2 months ago

famasf1 commented 2 months ago

I'm trying to build a self-contained console app with .Net Core 8. I picked win-x64 for publish and testing it on my Windows 11. The executable file inside folder .net8.0, runtime and Debug build work fine. However when I tried to run the app through release built with self-contained option. I got this error

Unhandled Exception: Newtonsoft.Json.JsonSerializationException: Unable to deserialize JsonRpcMessage.

Here's the full error log.


Newtonsoft.Json.JsonException: Error creating 'StreamJsonRpc.RequestIdJsonConverter'.
   ---> Newtonsoft.Json.JsonException: No parameterless constructor defined for 'StreamJsonRpc.RequestIdJsonConverter'.
     at Newtonsoft.Json.Serialization.JsonTypeReflector.<>c__DisplayClass22_0.<GetCreator>b__0(Object[] parameters) + 0x125
     --- End of inner exception stack trace ---
     at Newtonsoft.Json.Serialization.JsonTypeReflector.<>c__DisplayClass22_0.<GetCreator>b__0(Object[] parameters) + 0x1f4
     at Newtonsoft.Json.Serialization.JsonTypeReflector.GetJsonConverter(Object) + 0x7f
     at Newtonsoft.Json.Serialization.DefaultContractResolver.InitializeContract(JsonContract) + 0x7d
     at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract(Type) + 0x3b
     at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract(Type objectType) + 0x265
     at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey, Func`2) + 0xa0
     at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader, Type, Boolean) + 0x30
     at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader, Type) + 0x100
     at Newtonsoft.Json.Linq.JToken.ToObject(Type, JsonSerializer) + 0x7d
     at Newtonsoft.Json.Linq.JToken.ToObject[T](JsonSerializer) + 0x28
     at StreamJsonRpc.JsonMessageFormatter.ReadRequest(JToken) + 0x9a
     at StreamJsonRpc.JsonMessageFormatter.Deserialize(JToken) + 0x274
     --- End of inner exception stack trace ---
     at StreamJsonRpc.JsonMessageFormatter.Deserialize(JToken) + 0x2f3
     at StreamJsonRpc.JsonMessageFormatter.Deserialize(ReadOnlySequence`1, Encoding) + 0x6d
     at StreamJsonRpc.PipeMessageHandler.<DeserializeMessageAsync>d__23.MoveNext() + 0x715
  --- End of stack trace from previous location ---
     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x1c
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xbe
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task, ConfigureAwaitOptions) + 0x4e
     at StreamJsonRpc.HeaderDelimitedMessageHandler.<ReadCoreAsync>d__26.MoveNext() + 0x47c
  --- End of stack trace from previous location ---
     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x1c
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xbe
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task, ConfigureAwaitOptions) + 0x4e
     at StreamJsonRpc.MessageHandlerBase.<ReadAsync>d__22.MoveNext() + 0x1fc
  --- End of stack trace from previous location ---
     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x1c
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xbe
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task, ConfigureAwaitOptions) + 0x4e
     at StreamJsonRpc.JsonRpc.<ReadAndHandleRequestsAsync>d__175.MoveNext() + 0x29e
  --- End of stack trace from previous location ---
     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x1c
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xbe
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task, ConfigureAwaitOptions) + 0x4e
     at ThaiNationalIDJsonRpc.ThaiNationIDJsonRpcServer.<StartAsync>d__1`1.MoveNext() + 0x360
  --- End of stack trace from previous location ---
     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x1c
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xbe
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task, ConfigureAwaitOptions) + 0x4e
     at ThaiNationalIDJsonRpc.ThaiNationIDJsonRpcServer.<Main>d__0.MoveNext() + 0xfb
  --- End of stack trace from previous location ---
     at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x1c
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xbe
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task, ConfigureAwaitOptions) + 0x4e
     at ThaiNationalIDJsonRpc.ThaiNationIDJsonRpcServer.<Main>(String[] args) + 0x24
     at ThaiNationalIDJsonRpc!<BaseAddress>+0x86ac3c

I'm not sure why this issue is unique only through Release build. So unfortunately I have no idea what really caused it or can even do an attempted guess. If anyone know the answer, I thank you in advance!

AArnott commented 2 months ago

No parameterless constructor defined for 'StreamJsonRpc.RequestIdJsonConverter'

But there is one (by virtue of not defining any at all, C# will declare a default constructor.

That, and the fact that you said you're publishing a self-contained, arch-specific and release build app, suggests you may also be trimming. Enabling trimming in your build causes APIs that can't be clearly seen to be used to be removed. But that breaks reflection cases, such as serializers, which causes the error that you're seeing.

If you disable trimming, it'll work.

And no, we have no plans to invest time to making StreamJsonRpc work in a trimmed app at this point. But if you want to contribute support yourself, with tests, let us know what you plan and we may accept such a PR.