I am new to Azure logic apps. I have a service bus and pass a json object message to that service bus then I set up an action in logic apps to listen to my service bus. So everytime a new message come in to that service bus my logic apps will pick it up and send it to http.
My question is how can I grab the property from the message in service bus and pass it to my http action. I tried this
“Id” : “#{json(triggerBody()[‘ContentData’]).id}”
but it's not working
Who and how is sending the message on the queue?
I read a json message property (DestinationPath) in this way:
#{json(base64ToString(triggerBody()?['ContentData'])).DestinationPath}
Here is how my Logic App looks like
and in my case the message is sent from an Azure webjob as a BrokeredMessage:
string jsonMessage = JsonConvert.SerializeObject(myObject);
Stream streamMessage = new MemoryStream(Encoding.UTF8.GetBytes(jsonMessage));
BrokeredMessage msg = new BrokeredMessage(streamMessage);
client.Send(msg);
My precise setup to decrypt the base 64 message using the interface. Easy enough to type into the expression builder.
json(base64ToString(triggerBody()?['ContentData']))
ContentData of Service Bus messages is Base64 encoded, so you need to decode it first, e.g.
“Id” : “#{json(base64ToString(triggerBody()?[‘ContentData’])).id}”
Logic app now has expressions to decode Base 64 encoded value.
My requirement was to decode the encoded ServiceBus message to an Azure Function. I solved this using Logic App Expression, decodeBase64() which can accept a dynamic content of type string, in this case the 'Content'- Content of the message, and returns the decoded json string.
decodeBase64(triggerBody()?['ContentData'])
Find attached the screen shots for reference.
In the place holder for input to the action, include an expression and choose decodeBase64()
Get back to Dynamic Content tab to select 'Content' available from previous step, on hitting OK the expression would get generated
Related
I am creating a Azure Logic App. The workflow is triggered by "When a message is received in a topic subscription (auto-complete)".
The message is simple JSON format:
{
"FirstName":"Test",
"LastName":"User",
"CreatedAt":"2022-03-26T19:27:07.6885324-04:00"
}
I want to insert the record into Salesforce. But I am unable to insert the record as I am not able to extract properties from message.
You can use Parse_JSON in this case. As the result we receive from the trigger is of base64, we need to use
decodeBase64(triggerBody()?['ContentData'])
Here is the screenshot of my logic app:
RESULT:
I'm trying to use the Azure Service Bus api to purge messages from certain queues.
According to the documentation (https://learn.microsoft.com/en-us/rest/api/storageservices/clear-messages) I would do this using the following request:
https://myaccount.queue.core.windows.net/myqueue/messages
This seems simple enough, but the problem is I just cannot get this request to authorize correctly.
(result = 401 Unauthorized)
Apparently the signing process is rather elaborate and described here (https://learn.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key)
I had many attempts, like the following code:
var httpClient = new HttpClient();
using (HMACSHA256 hmac = new HMACSHA256())
{
var StringToSign = $"GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:{DateTime.UtcNow.ToString("o")}\nx-ms-version:2015-02-21\n\n\n\n";
var stringToSignHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(StringToSign));
var base64StringToSign = Convert.ToBase64String(stringToSignHash);
var signature = $"{base64StringToSign}, {MySecretKey}";
using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Delete, "https://myaccount.servicebus.windows.net/myqueue/messages"))
{
//requestMessage.Headers.Add("x-ms-date", DateTime.UtcNow.ToString());
requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("SharedKey", signature);
var result = httpClient.SendAsync(requestMessage).GetAwaiter().GetResult();
}
}
For MySecretKey I used my shared access policy key. I tried using as is, and also decoded base64 to ascii.
Does anyone have more success with this?
Are there more simple ways to access the api?
Thanks.
You can leverage the code here in different languages to generate the SAS token.
Updated:
Can you please confirm which API you are trying to execute? As per the code, you are calling the Delete method on myaccount.servicebus.windows.net (i.e. service bus resource). Delete API operation completes the processing of a locked message and deletes it from the queue or subscription. The samples/reference article that you have shared is for the delete messages from the storage queue. If your requirement is to purge all messages from the service bus queue then you need to use Recieve and Delete API. Alternative you can also use service bus explorer to purge the messages.
As an alternative you can use Service Bus Cloud Explorer which runs in the browser with logged-in user Azure account by default and have a purge functionality.
Keep in mind that it will take time to clear up queues or subscriptions. More messages it needs to purge; the more time it would take.
I am sending a string with an Azure Sphere dev kit using the provided function:
AzureIoT_SendMessage("Hello from sample App")
The message is sent to an IoT Hub and then routed to a storage blob with JSON encoding. If I look at the blob storage I get the following:
{"EnqueuedTimeUtc":"2019-05-22T12:33:42.2320000Z","Properties":{},"SystemProperties":{"connectionDeviceId":"fbea*****************6d**********************9c0","connectionAuthMethod":"{\"scope\":\"device\",\"type\":\"x509Certificate\",\"issuer\":\"external\",\"acceptingIpFilterRule\":null}","connectionDeviceGenerationId":"63************22","enqueuedTime":"2019-05-22T12:33:42.2320000Z"},"Body":"SGVsbG8gZnJvbSBzYW1wbGUgQXBw"}
The field "body" does not show at all the string sent ("Hello from sample App") but it shows "SGVsbG8gZnJvbSBzYW1wbGUgQXBw". Why is this happening? And how can I fix it?
I found that if I format the storage as AVRO (instead of JSON) the string is rendered correctly however the message becomes (literally) a blob and it cannot be used in streaming service such as powerBI (for example). However the message can be found, with some other mess stuff, in the blob (see picture below with the default string message)
See Microsoft's IoT Hub message routing documentation - specifically the Azure Storage section. It says "When using JSON encoding, you must set the contentType to application/json and contentEncoding to UTF-8 in the message system properties. Both of these values are case-insensitive. If the content encoding is not set, then IoT Hub will write the messages in base 64 encoded format."
This blog post further expands on the topic explaining that content type and encoding need to be set as specific headers.
On setting the headers:
If you are using the Azure IoT Device SDKs, it is pretty straightforward to set the message headers to the required properties. If you are using a third-party protocol library, you can use this table to see how the headers manifest in each of the protocols that IoT Hub supports:
FWiW, using PowerQuery (PQ) within PowerBi, I was able to decode the {body:xxxencoded_base64...} portion of the JSON file sent to blob by Azure IoT Hub.
My steps in PowerBI:
- Connect to blob account, container collecting the JSON files.
- Within PQ, click the double-arrow expand on the initial binary column
- For me, Column10 was the {body:xxx} column. Using PQ's Replace Values function, I removed the prefix "{body:" and the final "} - leaving just the encoded string.
- Create a new column in PQ, using this M-code: =Binary.FromText([Column10],BinaryEncoding.Base64)
- It's now a new Binary column, click the double-arrow and expand the binary. It'll reveal the decoded JSON table, complete w/ all your IoT telemetry.
HTHs
See also pending feature request for IoT-Hub:
feature request
I am trying to understand how to get content into a logic app email (or into the conditioning search in the logic app).
I have an IOT device sending a standard message to the hub (the demo temperature app). This works fine.
I have added a service bus and routing and again all ok.
I then want a logic app to send an email either using some of the content of the message, or even to use the conditional processing in the logic app.
I am using the connector in the logic app to the service bus.
When I try emailing dependant on the conditional "Content contains Startup" the email goes successfully but only down the false route.
When I try to put a JSON parse step in is returns invalid as the content isn't in JSON format.
The Error message:
InvalidJSON. The 'content' property of actions of type 'ParseJson'
must be valid JSON. The provided value
'e3sid2ZNZXNzYWdlVHlwZSI6IFN0YXJ0dXAsInRlbXBlcmF0dXJlIjogMzcuMzMsImh1bWlkaXR5IjogNjEuMjV9'
cannot be parsed: 'Unexpected character encountered while parsing
value: e. Path '', line 0, position 0.'.
It is a little hard to understand exactly where you problem is occurring but it sort of looks like your string is in base64.
You can try converting it using:
base64ToString(triggerBody()?['whateveryourvariablenameis'])
Check this out for screen shots and more information:
Azure Logic App service bus message content
I use Azure Service Bus to communicate IoT Hub with Node.js Functions. On Function side, I need to have access to message body as well as custom properties.
By retrieving messages elsewhere, I have noticed that my message in Service Bus consists of:
Body (the string set on IoT Device side).
Custom properties (include properties set on IoT Device side, IoT Device ID, and some additional metadata).
I have found online that in C# it is possible to access these custom properties using BrokeredMessage object. However, there is no mention on how to make this happen in Node.js. To give some details, I am printing the message as soon as it arrives to Function, using the following code:
module.exports = function(context, message) {
context.log('Message', message, 'of type', (typeof message));
...
}
What I am getting in the log console is:
message { test: true } of type object
Where "{ test: true }" is the content of a message set by IoT Device. No trace of properties though...
Is there some formal way or at least a trick to receive and extract these properties?
Thank you!
Browsing resources mentioned in the link posted by Ling Toh in a comment I got inspired to have a look at the context object.
Apparently, all of the Service Bus custom properties are available in context.bindingData.properties object.
In my case:
properties:
{
type: 'sometype', // <- this is the property I have set manually in IoT Hub message
'iothub-connection-device-id': 'mydeviceid',
'iothub-connection-auth-method': '{"scope":"somescope","type":"sometype","issuer":"external","acceptingIpFilterRule":null}',
'iothub-connection-auth-generation-id': 'someid' // <- These are added by IoT Hub
}