String concatenation issue with Azure Logic Apps - azure-logic-apps

I'm creating an ARM template that deploys an Web App (an Mvc Api) and a Logic App.
I'm attempting to define an HTTP Action within the Logic App such that it dynamically concatenates the base Uri of the Api as well as a property of the current item using splitOn and #triggerBody(). The base Uri itself is concatenated from a set of parameters in the ARM template into a variable variables('hockeyAppAPISettings').Uri.
Here's the relevant snipped of the action definition:
"actionName": {
"conditions": [ ],
"inputs": {
"authentication": {
"audience": "[variables('apiSettings').Authentication.Audience]",
"clientId": "[variables('apiSettings').Authentication.ClientId]",
"secret": "[variables('apiSettings').Authentication.Secret]",
"tenant": "[variables('apiSettings').Authentication.Tenant]",
"type": "ActiveDirectoryOAuth"
},
"method": "patch",
"uri": "[concat(variables('apiSettings').Uri, '/#{triggerBody()['Id']}/ScanningInProgress')]"
//"uri": "[concat(variables('apiSettings').Uri, '//#{triggerBody()[/'Id/']}//ScanningInProgress')]"
//"uri": "[concat(variables('apiSettings').Uri, '//##{triggerBody()[/'Id/']}//ScanningInProgress')]"
},
"type": "Http"
},
The "uri" section is what i'm struggling with. I've sprinkled various escape characters (\ and #) in differing patterns through out this.
I either can't get the deployment to succeed w/deployment errors like:
Unable to parse template language expression
'concat(variables('apiSettings').Uri,
'//#{triggerBody()[/'Id/']}//ScanningInProgress')': expected token
'RightParenthesis' and actual 'Identifier'. Please see
http://aka.ms/arm-template-expressions for usage details..'.
Or if I get the deployment working and then look at the code in the portal after deployment, the string concatenation doesn't seem to work properly. The variable doesn't get converted to its value.
I have validated that if I edit the Uri directly (via the portal HTML editor) using this: "uri" : "https://edited.azurewebsites.net/api/Packages/#{triggerBody()['Id']}/ScanningInProgress" the Logic App will make a patch call for each item that comes from the HTTP trigger.
What am I doing wrong?

You need to escape the inner single quotes, i.e. try
"uri": "[concat(variables('apiSettings').Uri, '/#{triggerBody()[''Id'']}/ScanningInProgress')]"
Alternatively you can use the dot notation to reference the property, i.e.
"uri": "[concat(variables('apiSettings').Uri, '/#{triggerBody().Id}/ScanningInProgress')]"

For me changing this
"uri": "[concat(parameters('APIMUrl_param'), '/sales-management/differential-reference-codes/v1/?instance=', parameters('APIDRCInstance_param'), '&filter=differentialReferenceCode%20eq%27', variables('varDRC'), '%27')]",
to this has worked
"uri": "#concat(parameters('APIMUrl_param'), '/sales-management/differential-reference-codes/v1/?instance=', parameters('APIDRCInstance_param'), '&filter=differentialReferenceCode%20eq%27', variables('varDRC'), '%27')",

Related

Use parametrized values with Azure Logic App

I'm working with an Azure LogicApp where the workflow have fixed values. Our DevOps tool is VSTS (Visual Studio Team Services) and because we have multiple environments to handle, I have to do some refactoring (using parametrized values) so in VSTS we'll be able to provide environment-specific values.
Thanks to 2 websites I found on Internet I managed to understand that there are 3 kind of parameters :
To understand my problem, here's my action :
I want to have my string "/work/documents" in a parameter value. So in the "Code view" I managed to use a parameter instead of a hard-coded value :
"triggers": {
"When_a_file_is_added_or_modified": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "#parameters('$connections')['sftp_1']['connectionId']"
}
},
"method": "get",
"path": "/datasets/default/triggers/onupdatedfile",
"queries": {
"folderId": "#{parameters('pathToRootFolder')}"
}
},
"recurrence": {
"frequency": "Hour",
"interval": 1
}
}
}
And in my parameters.json :
"sftp_1_path_root_folder": {
"value": "/work/documents"
}
Here's the final result in Visual Studio:
Am I missing something ? Why isn't the value displayed in the Designer ? Thank you for your help in advance !
When you are using Logic Apps parameters inside your Logic App definition, they are not resolved at design-time, but at run-time. Thus, you are not supposed to see them in the designer. If you run the workflow, you should be able to see the actual value at run-time.
If you want to resolve those parameters at deployment-time, then you would need to write directly from the ARM template using ARM parameters into the workflow definition. This is possible, but in some cases, it can become a bit more complex. That's why I prefer to make use of Logic Apps parameters as described here.

Using SFTP File Content in Azure Logic Apps

I have to pass File Name and File content to Azure function when new file is added or modified in SFTP folder. I am able to pass them but File content is getting passed as complex type json as follows:
{
"fileContent": {
"$content-type": "application/octet-stream",
"$content": "QWxvZnQgQidoYW0gU29obyBTcSAgICAg=="
},
"fileName": "testFile"
}
I just need to pass $content to Azure Function. My current code is as follows in logic app
"body": {
"fileContent": "#triggerBody()",
"fileName": "#triggerOutputs()['headers']['x-ms-file-name']"
},
How could I pass only content form FileContent to Azure function?
You should be able to just pass the content as-is. Logic Apps would decode the data and pass it as binary to the azure function (assuming the function can accept the binary content). You can pass the file name as a header.
If you want to attach the content as a property on a object, then you can use
"body": {
"fileContent": "#base64(triggerBody())",
"fileName": "#triggerOutputs()['headers']['x-ms-file-name']"
}
As you can see, you are getting a $content property, so you just need to access that property, and as is Base64 encoded, you need to decode it. Try this
"body": {
"fileContent": "#base64ToString(triggerBody()['$content'])",
"fileName": "#triggerOutputs()['headers']['x-ms-file-name']"
},
HTH

Need to read cookies value by it's name angularjs

I've cookie in my application and I need to read it using angularJS ngCookies.
When I exported the cookies from browser extension it looks like following json :
[
{
"domain": "localhost",
"hostOnly": true,
"httpOnly": false,
"name": "JSESSIONID",
"sameSite": "no_restriction",
"secure": true,
"session": true,
"storeId": "0",
"value": "00FC04BF082458FFE6F175C7E03F5712",
"id": 18
}
]
there can be more objects in this JSON along with 'JSESSIONID'. so I want to read only JSESSIONID's value.
my Code :
var jsessionCookie = $cookies.get('JSESSIONID');
console.log(" Cookies 'JSESSIONID' : "+jsessionCookie);
I'm getting undefined object.
The code you have seems fine, but the underlying issue is different.
You have your cookie marked as
"httpOnly": true
This means that cookie cannot be accessed by client side code including Angular.js.
The only way to access it is to change the code that generates the code so the cookie is not marked as httpOnly. There are some security considerations for making the change, so make sure you understand what you are doing.
You can read more about HttpOnly at OWASP web site.
To store a cokkie,
$cookies.put("cookie_name","cookie_value",{"expires":expireDate,"domain":"domain_name"});
To get a stored cookie
var cookieValue = $cookies.get("cookie_name);

How do I perform specific parentless requests using Restangular in a neat way?

Say I have an API endpoint at /users and another one at /cars. Naturally, a GET request to either of them will get all users or cars available. Now, a GET /users/74/cars should return all cars belonging to user 74.
But my app has many models related to cars, not just users, so more endpoints exist like /shops/34/cars and /mechanics/12/cars. For simplicity, I want all PUT/PATCH requests to be made to the main /cars endpoint.
At the moment of performing the save, Restangular will by default do a PUT request to the endpoint through which the item was loaded. But that endpoint do not exist.
It also provides a nice Restangular.setParentless(['cars']) method that will discard the first part of the url. However, I don't want to do this globally, but specifically for a particular element.
The neatest would actually do it globally, but restrict it for a specific method, like: Restangular.setParentless(['cars'], ['PUT']).
Anything like that around? Or am I overcomplicating it?
So far I tried stuff I don't like:
delete car.parentResource;
I would recommend using self reference links. A self reference link is a link which stores the route which should be used for GET/PUT/DELETE etc. on the item, rather than the URL from which it was pulled.
Example, update the mileage on one of user id 74's cars:
First, configure Restangular to look for a self link property called 'self' on each object.
RestangularProvider.setRestangularFields({
selfLink: 'self'
});
Next, make your call to get the cars. I'll assume that you have already modified your API to return a property called 'self' on each object that has the URL to it's proper API endpoint.
GET /users/74/cars
[
{
"id": 12,
"model": "Camaro",
"make": "Chevrolet",
"year": 1969,
"color": "red",
"odometer": 67294,
"license": "ABC12345",
"self": "/cars/12"
},
{
"id": 14,
"model": "Gallardo",
"make": "Lamborghini",
"year": 2015,
"color": "black",
"odometer": 521,
"license": "XYZ34567",
"self": "/cars/14"
}
]
We want to add some miles to one of them, and then save it. The entire Restangular code would look like:
Restangular.one('users', 74).all('cars').getList().then(function(cars){
cars[1].odometer = 613;
cars[1].put();
});
The PUT will go to /cars/14 instead of /users/74/cars/14. This is very useful for applications like yours that relate models as a graph rather than a strict hierarchical tree.

Explanation of Ext.direct API

I'm trying to get a grip on Ext.direct. On the official page there is this description of the API:
The purpose of the API component of the Ext Direct stack is to output the method configurations for Ext Direct to create client-side stubs. By generating these proxy methods, we can seamlessly call server-side methods as if they were client-side methods without worrying about the interactions between the client and server-side.
I just don't quite get what it means by ...to output the method configurations for Ext Direct to create client-side stubs. Would someone care to explain what this means at a grassroots level?
This will make more sense if you look at the output from the api.php resource included in the following example.
Note that this is being loaded on the page as a <script/> tag, ie:
<script type="text/javascript" src="php/api.php"></script>
When you open the src link you'll see the following JavaScript being generated by server-side PHP (see block of javascript code below).
In other words, PHP is doing the bit where it ... output(s) the method configurations for Ext Direct to create client-side (ie JavaScript) stubs.
Now the next question you should be asking if you want to make sense of this is: Why bother generating client side JavaScript using server side PHP (or other language of choice)?.
Ext.ns("Ext.app");
Ext.app.REMOTING_API={
"url": "php\/router.php",
"type": "remoting",
"actions": {
"TestAction": [{
"name": "doEcho",
"len": 1
}, {
"name": "multiply",
"len": 1
}, {
"name": "getTree",
"len": 1
}, {
"name": "getGrid",
"len": 1
}, {
"name": "showDetails",
"params": [
"firstName",
"lastName",
"age"
]
}],
"Profile": [{
"name": "getBasicInfo",
"len": 2
}, {
"name": "getPhoneInfo",
"len": 1
}, {
"name": "getLocationInfo",
"len": 1
}, {
"name": "updateBasicInfo",
"len": 0,
"formHandler": true
}]
}
};
This seems to be mimicking the way a WSDL works in that it can provide a service description and list all the options available for quering. In other words: Ext.Direct API is taking a concept from SOAP and applying it to a Javascript setting.
The back-end contains the API so this is the easiest place to generate a service definition with all the method names and signatures. Once the Ext.Direct API method stubs are provided (in the back-end), the front-end Ext.Direct library will do the plumbing and turn these into actual functionality that can be queried and used in JavaScript. Much in the same way as SOAP proxy classes can be automatically generated (in PHP/C# or Java) using the WSDL.
Personally I think this is a bit too airy-fairy for my liking. Most APIs are pretty straight forward and trying to implement something akin to WSDL actually makes consumption a lot harder than it would be if you just talk to it directly.

Resources