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.
Related
I'm using Azure eventhub with schema registry. I'm sending a message with a huge string.
The message has property JsonConent. I am using Avro schema for nullable string with a default value.
I am trying to convert the message to GenericRecord, when I consume it, but when the JsonContent is too large I have an error: Avro.AvroException - End of stream reached.
public async Task ProcessEventHandler(ProcessEventArgs arg)
{
var a = avroSerializer.Deserialize(arg.Data.EventBody.ToStream(), typeof(GenericRecord);
}
I am using Azure.Data.SchemaRegistry.ApacheAvro 1.0.0-beta.1,
Azure.Messaging.EventHubs 5.3.0-beta.4,
Azure.Messaging.EventHubs.Processor 5.3.0-beta.4
I found this issue, logged into the apache Jira board. Maybe Microsoft Azure is using it.
Our application uses temporary queues to direct service bus responses to the originating caller. We use the built-in ServiceStack.RabbitMq.RabbitMqServer to publish and handle messages.
Message<IReturn<ResponseDto>> message = BuildMessage(requestDto);
// get the temporary queue for the current IMessageQueueClient
string queueName = messageclient.GetTempQueueName();
message.ReplyTo = queueName;
// publish the message
messageclient.Publish(message);
However, capturing the response directly (below) will fail if the call throws an exception.
IMessage<ResponseDto> responseMessage = messageclient.Get<ResponseDto>(queueName, timeOut);
messageclient.Ack(responseMessage);
ResponseDto response = responseMessage.GetBody();
The body of the response message will be a ServiceStack.ErrorResponse causing responseMessage.GetBody() to return an empty object. And the error is not returned as responseMessage.Error.
We get around this by getting the body of the message as the raw JSV string and validating the result.
IMessage<string> responseMessage = messageclient.Get<string>(queueName, timeOut);
messageclient.Ack(responseMessage);
// get the body of the message as a string
string messageBody = responseMessage.GetBody();
// parse as error response
var error = messageBody.FromJsv<ErrorResponse>();
// if no response status, assume good
if (error?.ResponseStatus != null)
throw new Exception(error.ResponseStatus.Message);
// parse as response and return
return messageBody.FromJsv<ResponseDto>();
This works for most cases, however, if a string value in the returning RabbitMq message JSON contains a comma, the string is not contained in quotes in the message body JSV (this seems to be an issue in ServiceStack.Text when converting from JSON -> JSV using the JsonTypeSerializer)
which results in that field being incomplete, and the subsequent field being ignored.
Is there a better way to retrieve the exception? Or is there a workaround for the serialization issue?
There should be no converting JSON into JSV, they're different formats. JSV uses CSV-style encoding and escaping which is illegal in JSON which requires all string values to be quoted and strings escaped with \.
Essentially you should be deserializing the message using the exact Serializer and Type used to serialize it, if you do this there shouldn't be any issues.
ServiceStack's Rabbit MQ support serializes complex Type payloads as JSON so it's not clear where the JSV is coming from.
If you need to access the raw text payload you should use Rabbit MQ's low-level APIs instead of ServiceStack's RabbitMQ high-level APIs which automatically tries to deserialize complex types messages behind-the-scenes.
To get the raw text body you can do something like:
var rabbitMqClient = messageclient as RabbitMqProducer;
var mqResult = rabbitMqClient.GetMessage(queueName, noAck: false);
var props = msgResult.BasicProperties;
var bodyString = msgResult.Body.FromUtf8Bytes(); //normally JSON
I have two notification hub clients (nodejs and C#), both used for pushing messages into a hub.
The Node client sends perfectly fine, yet the C# client completes with no message being sent.
Below are the snippets for the used in each client.
C#
NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString("<Connection String>", "<Hub Name>");
var notice = #"{'aps':{'alert':'Notification Hub test notification'}}";
var result = await hub.SendAppleNativeNotificationAsync(notice, "<tag>");
Console.WriteLine(result.State);
NodeJS
var azure = require('azure');
var notificationHubService = azure.createNotificationHubService('<Hub Name>','<Connection String>')
var notice = "{'aps':{'alert':'Notification Hub test notification'}}"
notificationHubService.apns.send("<tag>", notice, function(error, res){
console.log(res);
});
Both work fine when sending Android notifications and messages sent directly from the Azure portal Test feature are fine.
Any assistance would be greatly appreciated.
Duncan,
I think the issue is because your payload is malformed as you are using single quotes. Try the following:
var notice = "{\"aps\":{\"alert\":\"Notification Hub test notification\"}}";
You can try to use the EnableTestSend feature and look at the NotificationOutcome property for the detailed error message. This will send a test send message to 10 devices.
bool enableTestSend = true;
NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString(connString, hubName, enableTestSend);
var outcome = await hub.SendWindowsNativeNotificationAsync(toast);
Console.WriteLine(outcome.State);
foreach (RegistrationResult result in outcome.Results)
{
Console.WriteLine(result.ApplicationPlatform + "\n" + result.RegistrationId + "\n" + result.Outcome);
}
TLDR - No '' (single quotes) allowed! Payload must containt alert key
Not a very exciting solution but...
If the notification payload contains single quotes even in a string literal the Notification hub will en-queue it without a malformed exception but when it reaches the APNS it will not be delivered as the payload is invalid according to them.
If the notification payload doesn't have alert key present it will also be en-queued but not delivered by the APNS
As already mentioned in my colleagues answers, you need to use double quotes in C# as a first step.
Second, you also need to escape the json characters:
Your payload should look like this:
var notice = "{{\"aps\":{{\"alert\":\"Notification Hub test notification\"}}}}";
Basically you escape the json braces { } by adding additional ones {{ }}.
This will send a valid json payload to the SendAppleNativeNotificationAsync() method. The payload now sent looks like this:
{"aps":{"alert":"Notification Hub test notification"}} (which is the correct notification format on iOS)
Here are the valid json payloads for iOS from the Apple Developer webpage.
You could always test if the json you are sending is a valid notification payload by using the 'Test Send' functionality in the Azure Notification Hub you are using.
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>();
Understand this is pre-release :)
When trying to use QueueInput in Azure WebJobs and sticking the hex string of a hash in the message.
public System.Guid GetOwner(CloudQueueMessage msg)
Looking at ilspy seems like it is trying to parse out $AzureJobsParentId and the JSON parser is throwing the exception I can get around it by encoding my hash in a JSON snippet but I'd prefer not to. Is this a known bug?
[QueueInput] will normally use JSON.Net to deserialize the queue message payload to the parameter type. So if the queue message is not JSON, you'll get a exception (which should then be wrapped in something more friendly).
You can also work around it by using a string parameter with [QueueInput], like:
public static void Function([QueueInput] string testqueue)
{
}
For string parameter, the SDK will give you the QueueMessage.AsString directly, without any JSON serialization.
FYI, $AzureJobsParentId is a special field placed on json payloads that identifies which function instance enqueued a message. This gets used when you enqueue a message with [QueueOutput]. You can then view that relationship in the SDK dashboard (http://blogs.msdn.com/b/jmstall/archive/2014/01/27/getting-a-dashboard-for-local-development-with-the-webjobs-sdk.aspx)