1
votes

We are using the Microsoft ServiceBus QueueClient to send message to the service bus. While receiving the message we are using the ServiceBus REST API. The deserialization of the body fails and we are not able to figure out the root cause.

The sample code to send message as follows:

MessagingFactory messagingFactory =
    MessagingFactory.CreateFromConnectionString(....);

Console.WriteLine("Creating Service Bus Queue Client...");

QueueClient queueSendClient = messagingFactory.CreateQueueClient(.);

// Send message M1 to the topic.
Console.WriteLine("Sending message.. ");

BrokeredMessage bm = CreateMessage();
queueSendClient.Send(bm);

The CreateMessage instantiates an BrokeredMessage that has a serialized object instance.

private static BrokeredMessage CreateMessage()
{
    JObject o1 = JObject.Parse(File.ReadAllText(@"..\..\requestJson.json"));

    string jsonMessage = JsonConvert.SerializeObject(o1);

    CommandMessage commandMessage = new CommandMessage();
    JsonCommand content = new JsonCommand("abc", "def", jsonMessage);

    List<Command> list = new List<Command>();
    list.Add(content);
    commandMessage.Initialize(list, false, false);

    var message = new BrokeredMessage(commandMessage);

    return message;
}

Note: The CommandMessage, JsonCommand, Command are decorated with [DataContract].

If we use the QueueClient for receiving also, then the receive of the message works fine. But in our case we are using the Service Bus Rest Client.

The receive message code is as follows:

const string ServiceBusNamespace = "mysb2015-ns";
string baseAddressHttp = "https://" + ServiceBusNamespace + ".servicebus.windows.net/";
string queueAddress = baseAddressHttp + QueueName;

HttpResponseMessage response = await this.httpClient.PostAsync(address + "/messages/head?timeout=60", new ByteArrayContent(new Byte[0]));

byte[] body = response.Content.ReadAsByteArrayAsync().Result;

DataContractSerializer deserializer = new DataContractSerializer(typeof(CommandMessage));
using (MemoryStream ms = new MemoryStream(body))
{
CommandMessage cmdMsg = (CommandMessage)deserializer.ReadObject(ms); 
}

The read object fails with the exception that the data at the root level is invalid:

System.Runtime.Serialization.SerializationException was unhandled HResult=-2146233076 Message=There was an error deserializing the object of type CommandMessage. The data at the root level is invalid. Line 1, position 1. Source=System.Runtime.Serialization

We looked at the content-type header in the response and it was application/xml;utf-8.

1

1 Answers

1
votes

Initializes a new instance of the BrokeredMessage class from a given object by using DataContractSerializer with a binary XmlDictionaryWriter.

When you send BrokeredMessage to queue, XmlDictionaryWriter is adding its type indication. If you use QueueClient for receiving, there will be no problem. Because it can resolve this type indication. But if you are using another than QueueClient you will have problem with deserialization.

Solution:

  1. Remove indicator before deserialize.
  2. Use other constructor of BrokeredMessage. BrokeredMessage(Stream messageBodyStream, bool ownsStream) and control the message body yourself.

In this article they explained the problem and the solution.