Error while deserializing Azure ServiceBus Queue message sent from node.js (azure sdk)
Asked Answered
A

5

11

Here's my scenario:

I'm sending an Azure ServiceBus Queue message from Node.js using the node azure sdk like so:

var message = {
    body: JSON.stringify({ foo: 'Bar' })
};

serviceBusService.sendQueueMessage('myQueue', message, function (error) {
    if (!error) {
        console.log('msessage sent');
    }
});

I have a c# worker role that is listening to the Queue:

QueueClient Client = QueueClient.CreateFromConnectionString(connStr, QueueName);

Client.OnMessage((receivedMessage) =>
{
    var body = receivedMessage.GetBody<string>();
});

When the GetBody method gets executed, i get the following error:

There was an error deserializing the object of type System.String. The input source is not correctly formatted

Argufy answered 20/2, 2015 at 19:48 Comment(0)
A
19

After some digging around, i found THIS article that helped me get a solution:


Client.OnMessage((receivedMessage) =>
{
    var bodyJson = new StreamReader(receivedMessage.GetBody<Stream>(), Encoding.UTF8).ReadToEnd();
    var myMessage = JsonConvert.DeserializeObject<MyMessage>(bodyJson);
});


If anyone has faced this issue and found a better solution, please let me know!

Thanks!

Argufy answered 20/2, 2015 at 19:48 Comment(0)
F
6

To anyone who found this question if they were getting this error from sending the message using Service Bus Explorer (like me).

Make sure you specify the correct message type in the drop down: enter image description here

Fatuous answered 18/12, 2019 at 1:31 Comment(0)
S
0

Thanks for the update, I was doing the reverse and this helped me. I thought I'd add to your solution for completeness. The DeserializeObject method needs the "MyMessage" class defining. In your original post, your JSON is:

{ foo: 'Bar' }

If we drop that into json2csharp (json2csharp.com) we now have the class required to complete your solution:

public class MyMessage
{
  public string foo { get; set; }
}

Of course, the dependency is having Newtonsoft.Json package added to your Visual Studio solution:

Install-Package Newtonsoft.Json -Pre
Stutzman answered 17/11, 2016 at 8:37 Comment(0)
V
0

Using the nuget package: Microsoft.Azure.ServiceBus

The following info is contained inside as as comment:

  1. If a message is only being sent and received using this Microsoft.Azure.ServiceBus client library, then the below extension methods are not relevant and should not be used.
  2. If this client library will be used to receive messages that were sent using both WindowsAzure.Messaging client library and this (Microsoft.Azure.ServiceBus) library, then the Users need to add a User property Microsoft.Azure.ServiceBus.Message.UserProperties while sending the message. On receiving the message, this property can be examined to determine if the message was from WindowsAzure.Messaging client library and if so use the message.GetBody() extension method to get the actual body associated with the message.

---------------------------------------------- Scenarios to use the GetBody Extension method: ---------------------------------------------- If message was constructed using the WindowsAzure.Messaging client library as follows: var message1 = new BrokeredMessage("contoso"); // Sending a plain string var message2 = new BrokeredMessage(sampleObject); // Sending an actual customer object var message3 = new BrokeredMessage(Encoding.UTF8.GetBytes("contoso")); // Sending a UTF8 encoded byte array object await messageSender.SendAsync(message1); await messageSender.SendAsync(message2); await messageSender.SendAsync(message3); Then retrieve the original objects using this client library as follows: (By default Microsoft.Azure.ServiceBus.InteropExtensions.DataContractBinarySerializer will be used to deserialize and retrieve the body. If a serializer other than that was used, pass in the serializer explicitly.) var message1 = await messageReceiver.ReceiveAsync(); var returnedData1 = message1.GetBody(); var message2 = await messageReceiver.ReceiveAsync(); var returnedData2 = message1.GetBody(); var message3 = await messageReceiver.ReceiveAsync(); var returnedData3Bytes = message1.GetBody(); Console.WriteLine($"Message3 String: {Encoding.UTF8.GetString(returnedData3Bytes)}"); ------------------------------------------------- Scenarios to NOT use the GetBody Extension method: ------------------------------------------------- If message was sent using the WindowsAzure.Messaging client library as follows: var message4 = new BrokeredMessage(new MemoryStream(Encoding.UTF8.GetBytes("contoso"))); await messageSender.SendAsync(message4); Then retrieve the original objects using this client library as follows: var message4 = await messageReceiver.ReceiveAsync(); string returned = Encoding.UTF8.GetString(message4.Body); // Since message was sent as Stream, no deserialization required here.

May it help you

Vain answered 11/10, 2019 at 12:26 Comment(0)
L
0

With the latest Service Bus client libraries (.NET, JS, Java, Python), you can send message(s) using the JS library like this:

const serviceBusClient = new ServiceBusClient("<connectionstring>");

const sender = serviceBusClient.createSender("<queuename>");
await sender.sendMessages([{
  body: {
    title: "hello"
  }
}]);

Note that .sendMessages takes a list as an input, even if you're just sending one message.

And get the body of the received message using .NET library like this:

await using var client = new ServiceBusClient("<connectionstring>");
ServiceBusReceiver receiver = client.CreateReceiver("<queuename>");

ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();
string body = receivedMessage.Body.ToString();
Console.WriteLine(body); //prints {"title":"hello"}
Lyndel answered 6/5, 2021 at 17:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.