Azure ServiceBus Message Serialization/Deserialization

25,471

Solution 1

It is possible to use JSON serialization to enable transferring these objects/entities.

Assume the following class is the type of which object instances will be sent to/received from an Azure Service Bus queue:

public class Customer{ public string Name { get; set; } public string Email { get; set; } }

--- Send ---

Find below a sample code (.NET Core 2.0 Console Application) to send a customer object instance:

QueueClient queueClient = new QueueClient(connectionString, queueName);
string messageBody = JsonConvert.SerializeObject(obj);
Message message = new Message(Encoding.UTF8.GetBytes(messageBody))
{
    SessionId = sessionId
};
await queueClient.SendAsync(message);

--- Receive ---

Find below an Azure Function (Service Bus Queue Trigger/.NET Standard 2.0) sample code to receive the message and deserialize it:

[FunctionName("ServiceBusQueueFunction")]
public static void Run([ServiceBusTrigger("taskqueue", Connection = "ServiceBusConnectionString")] Message message, TraceWriter log)
{
    Customer customer = JsonConvert.DeserializeObject<Customer>(Encoding.UTF8.GetString(message.Body));
}

The following NuGet packages were used/tested for the samples above:

  • Microsoft.Azure.ServiceBus (version 3.0.2).
  • Newtonsoft.Json (version 11.0.2).

Consider Reading: Find below the performance tips article for the JSON.NET: https://www.newtonsoft.com/json/help/html/Performance.htm


Design rationale: Built in POCO serialization support was removed in the latest Microsoft.Azure.ServiceBus. This was because "while this hidden serialization magic is convenient, applications should take explicit control of object serialization and turn their object graphs into streams before including them into a message, and do the reverse on the receiver side. This yields interoperable results."

https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messages-payloads

Solution 2

Neither of these worked for me because:

We are getting an exception when we try to parse the body of the message as JSON because the body of the message we are receiving is

"@\u0006string\b3http://schemas.microsoft.com/2003/10/Serialization/?\u000b{ \"a\": \"1\"}"

This is because "Brokered Message Initializes a new instance of the BrokeredMessage class from a given object by using DataContractSerializer with a binary XmlDictionaryWriter."

Ref: https://www.bfcamara.com/post/84113031238/send-a-message-to-an-azure-service-bus-queue-with

So I used this blog post instead: https://abhishekrlal.com/2012/03/30/formatting-the-content-for-service-bus-messages/

Example 1: Using string

When creating a BrokeredMessage with a string and the default (DataContract + Binary) serializer:

BrokeredMessage stringDefaultMessage = new BrokeredMessage("default string");

You can receive this message as:

string s = receiveMessage.GetBody<string>();

Solution 3

how to serialize/deserialize to send/receive the object?

Please refer to the demo code blow:

Send message:

var body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(obj));
await  queueClient.SendAsync(new Message { Body = body, ContentType = "text/plain" });

In the .net core WebJob

var body = Encoding.UTF8.GetString(message.Body);
var obj = JsonConvert.DeserializeObject<T>(body);

Test Result:

enter image description here

Share:
25,471

Related videos on Youtube

Username Not Exist
Author by

Username Not Exist

Super Duper Real

Updated on May 28, 2020

Comments

  • Username Not Exist
    Username Not Exist almost 4 years

    I am using a .NET Core application to send an object through an Azure Service Bus Queue and have it received by a Web Job (.NET Core as well.)

    My question is how to serialize/deserialize to send/receive the object?

    I found lots of references to the legacy BroakerMessage.GetBody() to receive the message, but not to the new .NET Core method. Please advise, thanks.

    Sender code:

    using Microsoft.Azure.ServiceBus;
    
    MyClass object = new MyClass();
    var message = new Message(object);
    await queueClient.SendAsync(message);
    

    Receiver code:

    using Microsoft.Azure.ServiceBus;
    
    public void ProcessQueueMessage([ServiceBusTrigger("queue")] Message message, TextWriter log)
    {
    }
    
  • Username Not Exist
    Username Not Exist almost 6 years
    Thank you so much, you are life saver, I have been stuck for couple of hours for this
  • g.t.w.d
    g.t.w.d over 5 years
    Did you actually test this? The Deserialize doesn't work for me because my message.Body has a bunch of crap that isn't json. This is my Message creation code: var queueBody = new QueueBody { Name = $"JSmith{i}" }; string messageBody = JsonConvert.SerializeObject(queueBody); var message = new Message { Body = Encoding.UTF8.GetBytes(messageBody), ContentType = "application/json" };
  • diegosasw
    diegosasw about 4 years
    But if the receiver does not know that the message is a Customer, where can be the message type be retrieved in order to dynamically decide which type to deserialize to?
  • diegosasw
    diegosasw about 4 years
    Is there any way to know the message type before deserialization?
  • johnstaveley
    johnstaveley almost 4 years
    Didn't work for me either. I get @\fbase64Binary\b3http://schemas.microsoft.com/2003/10/Seria‌​lization/�\u0002\u00‌​01{ at the start of the receving text and fails on this line: JsonConvert.DeserializeObject<MyObject>(body); with error 'Unexpected character encountered while parsing value: @.'