Retrieving object sent through a Message Queue - c#

I am building a Queue system and I have been able to send an object to a public queue located on another server.
What I cannot figure out is how to rebuild the object on the receiver side (I have the its definition on both ends).
Any ideas?

Have a look at the following MSDN example: http://msdn.microsoft.com/en-us/library/y918yfy2(v=vs.110).aspx
Basically, calling queue.Send(object) serializes the object with the default XmlMessageFormatter.
So you'll have to deserialize the message using the same serializer, and cast the result of the received Message.Body to the good type:
// Connect to the a queue on the local computer.
MessageQueue myQueue = new MessageQueue(".\\myQueue");
// Set the formatter to indicate body contains an Order.
myQueue.Formatter = new XmlMessageFormatter(new Type[] {typeof(MyProject.Order)});
// Receive and format the message.
Message myMessage = myQueue.Receive();
Order myOrder = (Order)myMessage.Body;

Related

Can I verify if message is sent successfully using Response<SendReceipt> in Azure Storage Queue

I am using the Azure Storage Queue Client to send base 64 encoded string messages. A very straight forward usage. I have the following code snippet:
var options = new QueueClientOptions
{
MessageEncoding = QueueMessageEncoding.Base64
};
var _queueClient = new QueueClient(settings.Value.ConnectionString, settings.Value.Name, options);
var message = JsonConvert.SerializeObject(messageObject, jsonSetting);
_queueClient.SendMessageAsync(message);
I know that SendMessageAsync( . . .) returns Response<SendReceipt> how do I use that to verify if a message is sent successfully or not ?
SendReceipt has MessageId and InsetionTime properties but the documentation does not specify what happens to these properties if message does not get sent. Does the queue simply returns null receipt or an object with default values ?
When you try to send a message to a queue using SendMessageAsync and if for some reason message is not sent, an exception is raised. You will not receive anything in the Response<SendReceipt>.
You will need to wrap your await _queueClient.SendMessageAsync(message); in a try/catch block. If no exception is raised that would mean the message is sent successfully.

How to remove #strin3http//schemas.microsoft.com/2003/10/Serialization/� received from service bus queue received in python script?

I have set the output of Azure stream analytics job to service bus queue which sends the data in JSON serialized format. When I receive the queue message in python script, along with the data in curly braces, I get #strin3http//schemas.microsoft.com/2003/10/Serialization/� appended in front. I am not able to trim it as the received message is not being recognized as either a string or a message. Because of this I cannot de-serialize the data.
This TechNet article suggests the following code:
// Get indices of actual message
var start = jsonString.IndexOf("{");
var end = jsonString.LastIndexOf("}") + 1;
var length = end - start;
// Get actual message
string cleandJsonString = jsonString.Substring(start, length);
Pretty primitive but whatever works I suppose...
The issue was similiar with the SO thread Interoperability Azure Service Bus Message Queue Messages.
Per my experience, the data from Azure Stream Analytics to Service Bus was sent via AMQP protocol, but the protocol of receiving the data in Python is HTTP. The excess content was generated by AMQP during transmission.
Assumption that receiving the message via the code below, please see https://azure.microsoft.com/en-us/documentation/articles/service-bus-python-how-to-use-queues/#receive-messages-from-a-queue. The function receive_queue_message with the False value of the argument peek_lock wrapped the REST API Receive and Delete Message (Destructive Read).
msg = bus_service.receive_queue_message('taskqueue', peek_lock=False)
print(msg.body)
According to the source code of Azure Service Bus SDK for Python include the functions receive_queue_message, read_delete_queue_message and _create_message, I think you can directly remove the excess content from the msg.body using the string common function lstrip or strip.
I ran into this issue as well. The previous answers are only workarounds and do not fix the root cause of this issue. The problem you are encountering is likely due to your Stream Analytics compatibility level. Compatibility level 1.0 uses an XML serializer producing the XML tag you are seeing. Compatibility level 1.1 "fixes" this issue.
See my previous answer here: https://stackoverflow.com/a/49307178/263139.
I had the same issue but in a .net solution. I was writing a service which sends data to a queue, and on the other hand, I was writing a service which gets that data from the queue. I've tried to send a JSON, like this:
var documentMessage = new DocumentMessage();
var json = JsonConvert.SerializeObject(documentMessage);
BrokeredMessage message = new BrokeredMessage(json);
await _client.SendAsync(message);
In this second service I was getting the JSON but with this prefix:
#strin3http//schemas.microsoft.com/2003/10/Serialization/�
I solved this problem by add DataContractJsonSerializer like that:
var documentMessage = new DocumentMessage();
var serializer = new DataContractJsonSerializer(typeof(DocumentMessage));
BrokeredMessage message = new BrokeredMessage(documentMessage , serializer);
await _client.SendAsync(message);
If you want to solve the problem in that way, you will have to add Data Attributes from System.Runtime.Serialization to the model:
[DataContract]
public class DocumentMessage
{
[DataMember]
public string Property1 { get; private set; }
[DataMember]
public string Property2 { get; private set; }
}
When using Microsoft.ServiceBus nuget package, replace
message.GetBody<Stream>();
with
message.GetBody<string>();

Azure Service Bus Queue sending a message in NodeJs to .NET client

I am sending a message from a C# worker to the Queue, then I am getting it on another C# worker and call
string body = message.GetBody<string>();
This works and I later de-serialize the string/JSON message.
Now I am trying to send the same message from NodeJS in form of a JSON message. When I try to receive it and
string body = message.GetBody<string>();
call this I get an exception saying the input is in incorrect format.
My message object on NodeJS looks like this
{
body: JSON.stringify(message)
}
Any ideas?
Got it fixed!
By default the .NET Azure Queue library uses a DataContractSerializer and a binary XmlDictionaryWriter to serialize the string message when using
new BrokeredMessage("my message");
So instead you need to use this
new BrokeredMessage(new MemoryStream(Encoding.UTF8.GetBytes("my message")), true);
and to read the message in C# you need to use
string body = new StreamReader(message.GetBody<Stream>(), Encoding.UTF8).ReadToEnd();
I also stopped wrapping my JSON.stringify message in an object and pass it directly to the sendQueueMessage. The send message code looks like this now:
serviceBusService.sendQueueMessage('my_queue', JSON.stringify("my message"), function(error){});
JSON.stringify outputs a UTF8 string so it is fully compatible with the C# code.

Recreating a Message in WCF

I am retrieving data from a server via WCF (I am the client). Unfortunately, the server (which I have no control of) is sometimes returning invalid XML.
In order to fix this, I plan to add a IClientMessageInspector (on the client), which modifies the Message before WCF has chance to parse the returned XML.
My first step was to implement IClientMessageInspector, but have it so it leaves the response unchanged (it should effectively be a no-op), but for some reason it causes the generated WCF method (client.getBar() below) to return a null object, rather than a populated object.
class UTF8Policer : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
Message revised = null;
var contents = new StringBuilder();
var writer = XmlWriter.Create(contents);
reply.WriteMessage(writer);
writer.Flush();
revised = Message.CreateMessage(reply.Version, reply.Headers.Action, XmlReader.Create(new StringReader(contents.ToString()));
revised.Headers.CopyHeadersFrom(reply);
revised.Properties.CopyProperties(reply.Properties);
reply = revised;
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
return null;
}
}
However, when running:
var client = new Foo_RPCClient();
var header = new header();
// This is what registers the inspector
client.Endpoint.EndpointBehaviors.Add(new FooEndpointBehaviour());
var response = client.getBar(ref header, new BarRequest());
... response is null. If I comment out the inspector registration, response works.
My conclusion is therefore that I'm somehow invalidating the message within AfterReceiveReply. Can anyone advise what the correct way is to re-create the message received?
Once I've got this working, I'm hoping it'll be trivial to fixup the XML within AfterReceiveReply, so that it actually does something useful.
Ref parameter wont work with WCF.
When you do the call to the service everything is pass as an input message serialized. Then the service deserialize it and do the work and finally it return a serialized response to the client that is deserialized on the client side.
The ref parameter might compile but in no way you retain the reference to a memory pointer in the client computer. You must use the response to return back the object.

Error updating Wcf message before hitting service using IDispatchOperationSelector

We are having to intercept a SOAP message before it hits our WCF service to perform the following steps:
Route the message to the correct method as the client is unable to provide us with a SOAPAction value.
Update the namespaces of the xml as the client is unable to add namespace information to the message.
The routing is not an issue, but we are having a problem with creating the message; once we recreate the message the body merely consists of "... Stream ...".
Before creating the message, the messageContent variable contains valid, correct xml.
private Message UpdateNamespaces(Message message, string methodName)
{
var memoryStream = new MemoryStream();
var xmlWriter = XmlWriter.Create(memoryStream);
message.WriteMessage(xmlWriter);
xmlWriter.Flush();
var messageContent = Encoding.UTF8.GetString(memoryStream.ToArray());
xmlWriter.Close();
// Update messageContent with corrected XML
memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(messageContent));
var xmlDictionaryReader = XmlDictionaryReader.CreateTextReader(memoryStream, new XmlDictionaryReaderQuotas());
var newMessage = Message.CreateMessage(xmlDictionaryReader, int.MaxValue, message.Version);
newMessage.Properties.CopyProperties(message.Properties);
return newMessage;
}
The messageContent is correct at the point at which we create the memoryStream, but as soon as I check the content of newMessage.ToString(), I'm getting the "... Stream ..." body content.
If anyone could help, I'd be very grateful as I'm out of ideas!
Many thanks
I think you are mixing behavior responsibilities.
IDispatchOperationSelector.SelectOperation is intended for routing decisions. It gives you a reference to the message, but the intention is to enable access to message properties. WCF does not expect the you to modify the message using this extension point. I can't say definitively, but the problem could be that simple.
If you want to alter the message namespace you should be using IDispatchMessageInspector. I suggest creating a second behavior for that task. Here's a nice Message Inspector example.

Categories