5

I am using .NET Core 2 for an application which needs to put a message on the Service bus and read by a legacy .NET 4.6 receiver. The receiver listens to messages from other legacy applications as well.

Legacy sender:

UserData obj = new UserData()
{
  id = 1,
  name = "Alisha"
};
BrokeredMessage message = new BrokeredMessage(consentInstated);
_client.Send(message);

Legacy Receiver:

var dataObj = objBrokeredMessage.GetBody<UserData>();
businessFunc(dataObj.id, dataObj.name);

.NET Core 2 sender: as described in https://stackoverflow.com/a/45069423/1773900

var ser = new System.Runtime.Serialization.DataContractSerializer(typeof(UserData));
var ms = new MemoryStream();
ser.WriteObject(ms, objUserData);
var message = new Message(ms.ToArray());
_client.Send(message);

However, the reciever fails to deserialize the message and throws the following error

System.Runtime.Serialization.SerializationException: There was an error deserializing the object of type UserData. The input source is not correctly formatted. ---> System.Xml.XmlException: The input source is not correctly formatted.

What can I do to make both senders work with the same receiver?

lohiarahul
  • 1,432
  • 3
  • 22
  • 35

3 Answers3

9

BrokeredMessage is using XML Binary Reader to deserialize the messages. So your sending part should look like this:

var ser = new DataContractSerializer(typeof(UserData));
var ms = new MemoryStream();
XmlDictionaryWriter binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(ms);
ser.WriteObject(binaryDictionaryWriter, obj);
binaryDictionaryWriter.Flush();
var message = new Message(ms.ToArray());
Mikhail Shilkov
  • 34,128
  • 3
  • 68
  • 107
  • 2
    The receiver can now parse the object but it loses values, and the properties are all set to null – lohiarahul Nov 22 '17 at 23:43
  • There seems to be a problem in the way the data is serialized. The byte array formed is different from what the BrokeredMessage creates. – lohiarahul Nov 23 '17 at 03:37
  • 1
    @lohiarahul I just tested and sending from new client to old client works with my code. Could you identify which difference your messages have (receive `Stream`, convert to `string` and compare)? E.g. could it be the message classes are in different namespaces? – Mikhail Shilkov Nov 23 '17 at 08:28
  • Is your receiver the same as mentioned in the question? I created a byte array using the BrokeredMessage and one with the solution you provided. The arrays created are not the same. Even the length differs. – lohiarahul Nov 27 '17 at 03:42
  • Yes, same. Please convert both arrays to string to see the difference. – Mikhail Shilkov Nov 27 '17 at 06:39
  • It works. Turns out that the `UserData` had two slightly different implementations with the same name in different namespaces at the receiver and the sender. Bummer. – lohiarahul Dec 01 '17 at 00:05
  • This answer is a life saver! Thanks @MikhailShilkov – Vinod Jun 09 '20 at 17:52
3

We could send serialize json Object string directly from .net core side, and we could get the message with following code in the .net side. It works correctly on my side.

var dataObj = message.GetBody<UserData>(new DataContractJsonSerializer(typeof(UserData)));

.net core side send message code:

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

.net side receive message code:

var dataObj = message.GetBody<UserData>(new DataContractJsonSerializer(typeof(UserData)));
Tom Sun - MSFT
  • 24,161
  • 3
  • 30
  • 47
2

I also encountered the same problem, but neither solution worked. For me below code works

// model is the object that you want to sent to Topic
Model model = new Model();
var serializator = new DataContractSerializer(typeof(string));
var json = JsonConvert.SerializeObject(model);
var memoryStream = new MemoryStream();
XmlDictionaryWriter binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(memoryStream);
serializator.WriteObject(binaryDictionaryWriter, json);
binaryDictionaryWriter.Flush();
// below message can be sent to Topic via .NET Core  and will be properly deserialized in .NET Framework subscriber
var message = new Message(memoryStream.ToArray());
var client = new TopicClient(_endpoint, _channelName );
await client.SendAsync(message);