Wednesday, July 8, 2020

Microsoft Flow - Avoid Infinite Loop on Sharepoint Lists

In Flow triggers on a Sharepoint list, we have either to trigger on Create or Create and Modify. When we use triggers on Modify and if the flow logic has functionality to Update Current Item, then upon running this action, it triggers the flow again and thus leads to infinite internal loop.

The reason is all update actions, could be our own HTTP Rest API or the Update Item action, both would go though standard process and these updates would trigger any flows configured to run on modify. 

Till Microsoft  comes up with different actions to update, we can leverage Trigger Conditions, available in Trigger Settings.

Trigger conditions are basically, extra conditions we can configure to make sure the flow executes only if they are met. Like, run only if Status is Complete. 

And, to avoid this infinite looping, I follow below 2 approaches, based on the situation.

Approach 1: If we are using any System Account for all the connections, this would say any updates happened through a Flow would set the Modified By to the System Account. So, in this case, I use the trigger condition as to run only if the Modified by is no the System Account. 

In this way, even if the record is updated through different flow, no flow would be triggered. 

And the trigger condition is
                    @not(contains(triggerBody()['Editor']?['Claims'],'adminaccount@company.com'))

Here I used Claims property. we can use any other property like Display Name, email etc.


Approach 2: If we are not using dedicated Accounts, then we create a new DateTime column named FlowRunDate. And, in every update action, we make sure to set this column value to UtcNow().

Thus, if any update happened through flow, we would have FlowRunDate and Modified as same values. 
If its updated manually, Modified date changes, but not FlowRunDate. 

We use this condition to control the flow execution. And, the conditions is,

@or(
          empty(triggerBody()?['FlowRunDate']),
          greaterOrEquals(
                    ticks(triggerBody()?['Modified']),
                    ticks(addSeconds(triggerBody()?['FlowRunDate'],10))
              )
       )

Here the first condition to check if the field value is empty, i.e. for already existing records, it will be helpful. And, the section condition is we add 10 seconds to the FlowRunDate field value and compare with Modified field. If the difference is more than it, then the update is happened by external person ad thus trigger the flow.

We can have 5 seconds or soem other value, but some time is needed as there are chances that there could some fraction of seconds difference from Modified Date field from other fields in update event.




Saturday, July 4, 2020

Send Adaptive Cards to Teams through Microsoft Flows

There is lots of progress happening in Providing functionalities / actions to Connect Microsoft Teams  through Power Automate. In this article, we will go through sending Adaptive Cards through Flows. 

Before we proceed, a quick gist about Adaptive Cards is, these are JSON formatted object content, rendered as UI in the Native Apps, like Teams, Outlook etc. For more details, can refer to https://adaptivecards.io/ . We Also have Card Designer IDE to drag and drop the controls and configure the properties. Once we design the UI, we can copy the JSON object and use in Flows to send it.

Flows have 4 different actions to send Adaptive Cards

These are, either to send to a user / teams channel and to send a card or wait for the response too.

All these 4 actions have sections for recipients, could be the user or the team and channel. Then, the Message section where we provide the JSON object. In wait for response card, we would have 2 more fields, one is the flag to say weather to send update card upon response  and the other one is with the Update message. As of now, Update message accepts plain text only. 

It would be cool, if they enable JSON object for update message too. 


A sample JSON, configured for demonstration is 
 {  
   "type": "AdaptiveCard",  
   "body": [  
     {  
       "type": "TextBlock",  
       "size": "Medium",  
       "weight": "Bolder",  
       "text": "Ticket Details"  
     },  
     {  
       "type": "ColumnSet",  
       "columns": [  
         {  
           "type": "Column",  
           "items": [  
             {  
               "type": "Image",  
               "style": "Person",  
               "url": "https://lh3.googleusercontent.com/ogw/ADGmqu9GlzolarU9-XLK_gQi4fzgEuJp1pFa8kqHN0Xa=s192-c-mo",  
               "size": "Small"  
             }  
           ],  
           "width": "auto"  
         },  
         {  
           "type": "Column",  
           "items": [  
             {  
               "type": "TextBlock",  
               "weight": "Bolder",  
               "text": "LaxmiNarayana Ruttala",  
               "wrap": true  
             },  
             {  
               "type": "TextBlock",  
               "spacing": "None",  
               "text": "Created July, 4th 2020",  
               "isSubtle": true,  
               "wrap": true  
             }  
           ],  
           "width": "stretch"  
         }  
       ]  
     },  
     {  
       "type": "TextBlock",  
       "text": "Add an adaptive card to send feedback form to assigned users. Upon receving the response, update the sharepoint list and send notification email to our admin department. ",  
       "wrap": true  
     },  
     {  
       "type": "FactSet",  
       "facts": [  
         {  
           "title": "Department:",  
           "value": "Finance"  
         },  
         {  
           "title": "Expected By:",  
           "value": "July 15th 2020"  
         }  
       ]  
     }  
   ],  
   "actions": [  
     {  
       "type": "Action.OpenUrl",  
       "title": "View Ticket",  
       "url": "http://www.luckytechshare.blogspot.com"  
     }  
   ],  
   "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",  
   "version": "1.2"  
 }  

We can refer any dynamic content in above data sample, could be from a sharepoint list content or other.

Once I configure it in the flow action and execute it,

it will be appearing on teams as below,
This is sent through the Flow Bot and also we would see the connector account details (used for this action in the flow) to the bottom of card, to avoid spamming.

If we want to capture any information through the card,we use Wait for a response action and configure input controls in the card. Upon submitting the info, the flow control receives the data in JSON object. It would have responder details and time stamp of it.

 {  
  "responseTime": "2020-07-04T11:38:14.4164791Z",  
  "responder": {  
   "objectId": "c3ede2bd-8341-4154-a3ae-4df6cf742e3a",  
   "tenantId": "a0ccad62-05f5-48bc-975b-c170b08d4ac9",  
   "email": "lucky@tmsdemo.onmicrosoft.com",  
   "userPrincipalName": "lucky@tmsdemo.onmicrosoft.com",  
   "displayName": "LaxmiNarayana Ruttala"  
  },  
  "submitActionId": "Assign To Me",  
  "data": {  
   "teamAadId": "8e92d18c-4f2f-4cdb-8980-70cf01ce6e76",  
    "inputField":"value"  
  }  
 }  

We can access this info in the flow and perform required actions.

We can also mention users in the adaptive cards. We simple need to add email id of user enclosed in 'at' tag.
              eg: <at>lucky@tmsdemo.onmicrosoft.com</at>

For some reason, this is not working in actions with wait for response. For those, we can add JSON object as below by referring the user ID and refer the 'at' tag notation at places needed.

 "msteams": {  
   "entities": [  
    {  
     "type": "mention",  
     "text": "<at>AssignedUser</at>",  
     "mentioned": {  
      "id": "8:orgid:c3ede2bd-8341-4154-a3ae-4df6cf742e3a",  
      "name": "Lucky"  
     }  
    }  
   ]  
 }  

Happy Coding :-)