Thursday, October 24, 2019

The template language expression 'xxx' cannot be evaluated because property 'xxx' doesn't exist. Property selection is not supported on content of type 'application/xml'

I tried to use the orderID node's value in the subject of the send email action from the triggerBody(),the message to trigger logic app is as below
<purchaseOrder>
    <orderID>PO0029</orderID>
    <orderDate>2019-10-20</orderDate>
    <description>Discount applied on the Order</description>
    <shipTo>
        <name>Mike Taylor</name>
        <street>MG Road</street>
        <city>Pune</city>
        <state>MH</state>
        <pin>411001</pin>
        <country>India</country>
    </shipTo>
    <billTo>
        <name>Mike Taylor</name>
        <street>MG Road</street>
        <city>Pune</city>
        <state>MH</state>
        <pin>411001</pin>
        <country>India</country>     
        <emailID>maheshkumar.tiwari@emtecinc.com</emailID>
    </billTo>
</purchaseOrder>

However I was encountered with an error
property doesn't exist


InvalidTemplate. Unable to process template language expressions in action 'Send_email' inputs at line '1' and column '1607': 'The template language expression 'triggerBody().purchaseOrder.orderID' cannot be evaluated because property 'purchaseOrder' doesn't exist. Property selection is not supported on content of type 'application/xml'. Please see https://aka.ms/logicexpressions for usage details.'.


Why it happened




It is clear from error that the Logic App runtime was not able to find purchaseOrder property although the node purchaseOrder is present and another thing it’s pointing out is that property selection is not supported on content of type ‘application/xml’.



And what I was doing is sending xml as message body, content type as ‘application/xml’ and  with 'triggerBody().purchaseOrder.orderID' expression I was asking logic app runtime to fetch the value of orderID under purchaseOrder of triggerBody() with assumption that triggerBody() always returns JSON upon which property selection can be done  – And this assumption was wrong.

triggerBody() is an Azure Workflow built-in FUNCTION, which is used to access the output of trigger(shorthand for trigger().outputs.body) and it’s return type is String. But when you trigger a logic app with content type as ‘application/JSON’ , the logic app runtime implicitly applies the JSON parsing on it and thus the triggerBody() returns JSON document as output.

To get the entire body you just use triggerBody() and with the property suffix added to it , value of that field is returned.

So if I had to pass following JSON message
{
   "orderID": "PO0029",
   "orderDate": "2019-10-20",
   "description": "Discount applied on the Order",
   "shipTo": {
      "name": "Mike Taylor",
      "street": "MG Road",
      "city": "Pune",
      "state": "MH",
      "pin": "411001",
      "country": "India"
   },
   "billTo": {
      "name": "Mike Taylor",
      "street": "MG Road",
      "city": "Pune",
      "state": "MH",
      "pin": "411001",
      "country": "India",
      "emailID": "maheshkumar.tiwari@emtecinc.com"
   }

}

then  triggerBody() would  give me above whole json whereas 'triggerBody().billTo.emailID' would give me value as maheshkumar.tiwari@emtecinc.com

In my case , here the content passed on was XML and therefore no JSON parsing was applied and thus leading to error.


What to do


Logic app is very well equipped to process XML message apart from JSON, however if any expressions(functions) are to be applied on it then it has to be explicitly handled either by casting it to JSON using xml based functions.

Here, I need to get value of  orderID node thus the message has to be casted to JSON and then access the property (property is JSON = node in XML) by following expression
                          json(xml(triggerBody())).purchaseOrder.orderID

In the above expression first triggerBody() (which is string) is casted in XML using xml() function and then casted it  in JSON using json() function. And it worked absolutely fine.

However with understanding that json function is used to convert xml then it can do it directly , thus directly passed on triggerBody to it and it works too.
json(triggerBody()).purchaseOrder.orderID

Note : First triggerBody is converted to JSON by using  json(triggerBody()) and then using dot operator particular property is accessed

Out of curiosity, the another syntax which can be used

json(triggerBody())['purchaseOrder']['orderID']


  



No comments:

Post a Comment