0

`I'm trying to send a JSON message over a WebSocket connection using C#. The message I'm trying to send is a serialized object that needs to be nested inside a JSON array.

The class structure for my message is:

public class BulkSubscribeMessage
{
    [JsonProperty("_event")]
    public string Event { get; set; }
    [JsonProperty("tzID")]
    public int TimeZoneId { get; set; }
    public string Message { get; set; }
}

I've serialized an instance of BulkSubscribeMessage and attempted to nest it within a JSON array to send over WebSocket. I'm using JsonConvert.SerializeObject to do this. My code is as follows:

public async Task Subscribe(List<EconomicEvent> events)
{
    StringBuilder sb = new StringBuilder();
    sb.Append("pid-eu-177:%%pid-eu-172:%%pid-eu-8826:%%pid-eu-1175153:%%pid-eu-169:%%pid-eu-8827:%%pid-eu-956731:%%");

    foreach (var eEvent in events)
    {
        sb.Append($"event-eu-{eEvent.Id}:%%");
    }

    // Removing the last two '%%'
    if (sb.Length > 2) sb.Length -= 2;

    BulkSubscribeMessage message = new BulkSubscribeMessage()
    {
        Event = "bulk-subscribe",
        TimeZoneId = 16,
        Message = sb.ToString()
    };

    // Create a list with one element: the serialized message
    var messageList = new List<string>
    {
        JsonConvert.SerializeObject(message)
    };

    // Serialize the list of messages
    string jsonString = JsonConvert.SerializeObject(messageList);

    var buffer = Encoding.UTF8.GetBytes(jsonString);
    await _client.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
}

When I send this message, I don't get a response from the server. When I inspect the WebSocket traffic in the Chrome developer console, the expected message format is:

[
    "{\"_event\":\"bulk-subscribe\",\"tzID\":16,\"message\":\"pid-eu-177:%%pid-eu-172:%%pid-eu-8826:%%pid-eu-1175153:%%pid-eu-169:%%pid-eu-8827:%%pid-eu-956731:%%event-eu-1:%%event-eu-2:...\"}"
]

However, when I print out the jsonString in my code, the format looks correct, but I am not getting any response from the server.

How can I correctly send this JSON message over the WebSocket connection? Are there any issues with my serialization or the WebSocket message sending process? I am using the System.Net.WebSockets.ClientWebSocket for the WebSocket connection.

WebSocket URL: wss://streaming.forexpros.com/echo/321/dgwckgeo/websocket

In the following screenshot you can see I sent two commands. First one is the format my client app generates. The WebSocket server requires it to be encapsulated in quotation marks, as you can see after the second command I immediately got a response back

I tried to serialize my command in an array, aiming to get the same format as the correct command sent by web browser client, but with no success. I still didn't manage to get the quotation marks.

Mattia
  • 11
  • 2
  • The JSON string is wrong. That's an array of strings, not objects. You can replace all the string manipulation code with just `var buffer = JsonSerializer.SerializeToUtf8Bytes(events);`. This avoids errors, is much faster and uses a lot less memory than manual serialization – Panagiotis Kanavos Jun 20 '23 at 14:28
  • Or, if you want to compose events and messages, `var message = new BulkSubscribeMessage(){..., Message = events};` and then `JsonSerialize....(message);`. *Don't* convert `events` to a string. You may have to change `Message` to a generic class. As far as JSON is concerned, a string value is nothing more than an opaque string value – Panagiotis Kanavos Jun 20 '23 at 14:30
  • @PanagiotisKanavos my concern is that the server is not receiving the expected message in the correct format. even hardcoding the message: string jsonString = JsonConvert.SerializeObject(new[] { "{\"_event\":\"bulk-subscribe\",\"tzID\":16,\"message\":\"pid-eu-177:%%pid-eu-172:%%pid-eu-8826:%%pid-eu-1175153:%%pid-eu-169:%%pid-eu-8827:%%pid-eu-956731:%%event-eu-1:%%event-eu-2:...\"}" }); _client.Send(jsonString); doesn't produce any response from the server. the same exact message works if sent by an online websocket tester. – Mattia Jun 20 '23 at 14:35

1 Answers1

0

you are serializing twice. try to replace

var messageList = new List<string>
    {
        JsonConvert.SerializeObject(message)
    };

    // Serialize the list of messages
    string jsonString = JsonConvert.SerializeObject(messageList);

with

 string jsonString = JsonConvert.SerializeObject( 
                                    new BulkSubscribeMessage[] { message });
// or more simple
 string jsonString = "[" + JsonConvert.SerializeObject(message) + "]";

Serge
  • 40,935
  • 4
  • 18
  • 45