question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Can't serialize poco class

See original GitHub issue

I’m sening a POCO with a SignalR hub then, it gets sent to my subscribed client, but the data is lost.

The data I’m sending

public class WorkerOrderViewDto
    {
        public int Id { get; set; }
        public string UserName { get; set; } = string.Empty;
        public ICollection<SandwichDto> Sandwiches { get; set; } = new List<SandwichDto>();
        public OrderState State { get; set; }
    }
public enum OrderState
    {
        OrderPlaced,
        InTheOven,
        ToBeDelivered,
        Delivered,
    }

The Hub

public class WorkerViewOrderHub : Hub<IWorkerViewOrderClient>
    {
    }

    public interface IWorkerViewOrderClient
    {
        Task ReceiveOrderAddedAsync(WorkerOrderViewDto orders);
    }

Sending the data

private readonly IHubContext<WorkerViewOrderHub, IWorkerViewOrderClient> _workerViewHub;
public async Task<ActionResult> AddOrderAsync([FromBody] AddOrderDto addOrderDto)
        {
            var userId = _userManager.GetUserId(HttpContext.User) ?? throw new InvalidCommandException();
            addOrderDto.UserId = userId;
            addOrderDto.CustomerId = userId;

            var result = await _serverOrderService.AddOrderAsync(addOrderDto);

            var orderView = (await _serverOrderService.GetPendingOrdersForWorkerAsync()).SingleOrDefault(o => o.Id == result);

            await _workerViewHub.Clients.All.ReceiveOrderAddedAsync(orderView);

            return new OkResult();
        }

SignalR Client

_connection.On<WorkerOrderViewDto>(HubNames.WorkerViewOrderHubNames.ReceiveOrderAddedAsync, OnOrdersModifiedAsync);

            Task OnOrdersModifiedAsync(WorkerOrderViewDto order)
            {
                Orders.Add(order);

                OrdersChanged?.Invoke();

                return Task.CompletedTask;
            }

Chrom debug inspection of the serialized data: https://imgur.com/gallery/m37ptwF

The client connects, gets the message, OnOrdersMidifiedAsync gets called, but the data is not serialized properly. Any idea what I’m doing wrong?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
szmaleccommented, Dec 10, 2019

@KuraiAndras I didn’t really like the idea of adding the JsonPropertyName attribute to each model used in communication with SignalR 😉 so I tried to solve the problem on the server side where “camelCase” serialization occurs:

services
    .AddSignalR()
    .AddJsonProtocol(options => {
        // Configure the serializer to not change the casing of property names, instead of the default "camelCase" names.
        // Default camelCase is not supported by used Blazor.Extensions.SignalR, because it does NOT allow to specify JSON deserialization options - it just uses eg. JsonSerializer.Deserialize<TResult1>(payloads[0]) and there is no option to pass JsonSerializerOptions to System.Text.Json.JsonSerializer.Deserialize():
        // https://github.com/BlazorExtensions/SignalR/blob/v1.0.0/src/Blazor.Extensions.SignalR/HubConnection.cs#L108 + https://github.com/BlazorExtensions/SignalR/issues/64
        // Idea taken from: https://docs.microsoft.com/en-us/aspnet/core/signalr/configuration?view=aspnetcore-3.1&tabs=dotnet#jsonmessagepack-serialization-options
        options.PayloadSerializerOptions.PropertyNamingPolicy = null;
    });

Models in messages incomming to client side are then deserialized without problems (WARN: for outgoing models camelCase is still applied but this is not problem - model are properly deserialized on server side). signalr_json

I have discovered that JsonPropertyName attribute is still required when using MessagePack otherwise we will encounter following exception on client side:

blazor.webassembly.js:1 Uncaught (in promise) Error: System.Text.Json.JsonException: The JSON value could not be converted to System.Decimal. Path: $.DecimalData | LineNumber: 0 | BytePositionInLine: 47. ---> System.InvalidOperationException: Cannot get the value of a token type 'String' as a number.
  at System.Text.Json.Utf8JsonReader.TryGetDecimal (System.Decimal& value) <0x24d8310 + 0x00018> in <90ed82de44024ca1bc6b68be1a1a7e32>:0 
  at System.Text.Json.Utf8JsonReader.GetDecimal () <0x24d8240 + 0x00008> in <90ed82de44024ca1bc6b68be1a1a7e32>:0 
  at System.Text.Json.Serialization.Converters.JsonConverterDecimal.Read (System.Text.Json.Utf8JsonReader& reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) <0x24d8188 + 0x00004> in <90ed82de44024ca1bc6b68be1a1a7e32>:0 
  at System.Text.Json.JsonPropertyInfoNotNullable`4[TClass,TDeclaredProperty,TRuntimeProperty,TConverter].OnRead (System.Text.Json.ReadStack& state, System.Text.Json.Utf8JsonReader& reader) <0x24d7f98 + 0x00030> in <90ed82de44024ca1bc6b68be1a1a7e32>:0 
  at System.Text.Json.JsonPropertyInfo.Read (System.Text.Json.JsonTokenType tokenType, System.Text.Json.ReadStack& state, System.Text.Json.Utf8JsonReader& reader) <0x2097e68 + 0x00078> in <90ed82de44024ca1bc6b68be1a1a7e32>:0 
  at System.Text.Json.JsonSerializer.HandleValue (System.Text.Json.JsonTokenType tokenType, System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& state) <0x2097a60 + 0x0009a> in <90ed82de44024ca1bc6b68be1a1a7e32>:0 
  at System.Text.Json.JsonSerializer.ReadCore (System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& readStack) <0x20947c8 + 0x00092> in <90ed82de44024ca1bc6b68be1a1a7e32>:0 
   --- End of inner exception stack trace ---
  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) <0x1c47900 + 0x000c8> in <bceea5edb42b4ad28e0d8ad9d8e3fe0f>:0 
--- End of stack trace from previous location where exception was thrown ---

  at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.InvokeSynchronously (Microsoft.JSInterop.JSRuntime jsRuntime, Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo& callInfo, Microsoft.JSInterop.Infrastructure.IDotNetObjectReference objectReference, System.String argsJson) <0x21badc0 + 0x00164> in <3eedf0ca90ca4e72bf6870618ca98c7c>:0 
  at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet (Microsoft.JSInterop.JSRuntime jsRuntime, Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, System.String argsJson) <0x22023f8 + 0x00090> in <3eedf0ca90ca4e72bf6870618ca98c7c>:0 
    at Object.endInvokeDotNetFromJS (http://localhost:13425/_framework/blazor.webassembly.js:1:9849)
    at Object.invokeJSFromDotNet (http://localhost:13425/_framework/blazor.webassembly.js:1:9475)
    at _mono_wasm_invoke_js_marshalled (http://localhost:13425/_framework/wasm/mono.js:1:179080)
    at wasm-function[6361]:0x11d724
    at wasm-function[1463]:0x3f118
    at wasm-function[616]:0x1373b
    at wasm-function[616]:0x1eb39
    at wasm-function[616]:0x1eb17
    at wasm-function[616]:0x1eb17
    at wasm-function[616]:0x1eb17
0reactions
galvesribeirocommented, Nov 27, 2019

If that is an API that is available on the original SignalR client and/or the JavaScript one yeah, we can have that.

The intent of this project is to wrap the JavaScript client and provide as much as possible the .Net API compatibility.

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - Json.net cannot serialize if the class does not have an ...
If property's class has an empty constructer then this property is serialized but if there is only one constructer that you have to...
Read more >
NonSerializedAttribute Class (System)
Indicates that a field of a serializable class should not be serialized. This class cannot be inherited.
Read more >
XmlSerializer Class (System.Xml.Serialization)
Serializes and deserializes objects into and from XML documents. The XmlSerializer enables you to control how objects are encoded into XML.
Read more >
SerializeReference Attribute? | Page 2
Is it really the case that a class can't serialize its own type reference? It's not a problem to add the extra interface...
Read more >
Can't serialize nested class with JsonUtility
I'm trying to make a small save system using Json and would like to be able to serialize a custom serializable class.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found