Complete a Dataverse Task by an Adaptive Card in Teams

Shows an animated gif of a Model-Driven App where a task is created. This task gets posted to a Teams Chat as an Adaptive Card. From this Adaptive Card the Task gets completed. Helping people stay in their flow of work, instead of opening the Model-Driven App.

In my previous blogpost we created tasks in Dataverse which we can interact with using the Model-Driven App. However, sometimes the user we assign a task to does not log in to our application as often as we would like. So, we need to bring them to attention a task is waiting for them. An excellent way to do this is by automatically sending them a chat message and posting an Adaptive Card! In this post I will go through the steps to set this up.

This will not be a crash course on all the ins and outs of every detail of Adaptive Cards. But more of an inspiration style post to get you started with your Adaptive Cards. I will however, show you how to set up the Cloud Flow to post this card to Teams. Including the ability to process a response from that Card.

Adaptive What?

Adaptive Cards are a way to create mini apps and post them too various channels. It will render a card inside the application you choose. Common ways you can use Adaptive Cards are in Microsoft Outlook e-mail or inside Chatbot applications like Power Virtual Agents. I like to use them to keep the user in their flow of work. If the user only needs to do minimal interaction with a record it is best to not let them log-in to a specific app to complete it. In my example this is a simple To Do Task, declaring it done with a single button from within a Teams chat!

Adaptive Cards are written in json format. Which means that the properties of a card are human readable. The complexity arises when cards get bigger, when you want to add dynamic data or add multiple kinds of actions a user can perform. Luckily, we do not have to start designing a card from scratch.

The Adaptive Card website not only has a lot of examples, but it also has a great designer. At first you might be intimidated by the number of options; I know I was! But it is best to start off building your own little card to get the hang of it and expand your knowledge from there. In fact, you might want to try recreating this example I am showing you right now!

Create the Adaptive Card

Let’s start by creating our Adaptive Card. In this Card we want to show the Task Subject and Description to the User. We also want to give them the option to open the Task in the Model-Driven App and eventually complete it from within Teams by pressing a button. To start off in the Adaptive Card Designer select the correct “Host App”, in our example Microsoft Teams. This will render the example of the Card correctly in the designer. Then press “New Card”.

Shows the Adaptive Cards designer highlighting to select Microsoft Teams as a host app.
Adaptive Card Designer Teams Chat

On the left-hand side of the screen, we can select which Elements we want in our Card. When adding elements, we get both a design and a schematic overview of the card in the Card Structure. On the right-hand side, we can set the properties of the specific elements.

  • Add a TextBlock to eventually contain the “Subject of the Task”. This is also the temporary text I put in the Text property. Make the text bold by setting the Weight optionset to bolder. Set the Size to Larger.
  • Add another TextBlock with the “Description of the Task”. Again, just a placeholder for now.
  • Add an ActionSet element. This will be where we place our buttons. Add those buttons by pressing “Add an action” while the ActionSet is selected.
    • Choose Action.OpenUrl. Add “More Details” to the title. Put url as a placeholder in the Url property.
    • Choose Action.Submit. With the title “Complete Task”. This will submit the Card back to the Power Automate Cloud Flow. In this example we don’t need any data from the Card.
Shows the Finish Adaptive Card Design in the adaptivecards.io designer.
Finished Design of the Card

This completes the design of the Adaptive Card, and it should look like the Card above. The Card Payload Editor will contain the json we will use in the Power Automate Cloud Flow. For reference I have included that below.

{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.4",
  "body": [
    {
      "type": "TextBlock",
      "text": "Subject of the Task",
      "wrap": true,
      "weight": "Bolder",
      "size": "Large"
    },
    {
      "type": "TextBlock",
      "text": "Description of the Task",
      "wrap": true
    },
    {
      "type": "ActionSet",
      "actions": [
        {
          "type": "Action.OpenUrl",
          "title": "More Details",
          "url": "Url"
        },
        {
          "type": "Action.Submit",
          "title": "Complete Task",
          "style": "positive"
        }
      ]
    }
  ]
}

On to the Cloud Flow

We now have a card to work with, so let’s create a Cloud Flow to actually post this to a chat. Our trigger is “When a task row is added”. But I do not want to post a chat message for every Task that gets created, I only want it to my colleagues who are in the Logistic Team. This team will not look into the Model-Driven App often. We start by gathering meta data and doing a preliminary check.

Shows an overview of the entire Cloud Flow to post an Adaptive Card to a Teams Chat when a Task is created.
Cloud Flow Overview

The Owner of the Task will contain the assignee of the Task. It will contain a team or a user. For this example, I take a shortcut and expect it to always contain a user. For this User we want to retrieve their email address. And while we query the user, we can also grab and filter related data of this user. In this case we expand the user table with the team membership association table. A many to many table between the user and the team. We filter this table with the team name ‘Logistic’.

teammembership_association($select=name;$filter=name eq 'Logistic')

In the following condition we check if the field “teammembership” is empty.

empty(outputs('Get_email_address_from_owner_of_the_Task_expand_on_teammember')?['body/teammembership_association'])

And if it’s empty, we terminate the Cloud Flow. The Task is not assigned to a user in the team Logistic and thus we don’t want to send a Teams Chat with the Adaptive Card.

Shows a Power Automate action and a condition. In the action the internalemailaddress is grabbed from the Owner of the task. Also is expanded to grab the teammembership_association with a filter on the name for the Logistic team. The condition checks if this is empty. If it's empty, the Flow will terminate.
Teammember Association of User

Inject the Adaptive Card with dynamic data

In this blogpost I show how to create the Model-Driven App Record Url. We will use the same technique, but I learned of a different way to navigate. You actually do not need the appid in the url. We can change the appid query parameter to the appname! This is 1 less api call to Dataverse in the Cloud Flow and thus will improve performance.

Shows how to compose a Model-Driven App Task record. Highlights to use the App name in the url.
Model-Driven App Task Record Url

Now that we have all data, we need to update the Adaptive Card. Create a Compose action and copy-paste the Card json in it. Replace the text properties of the json with the actual subject and description attributes from the Task. And replace the url property with the output of the Compose of the Create Record Url.

Shows a Power Automate Compose action where the Adaptive Card json is injected with data from the Task.
Compose Adaptive Card

Post it to Teams

Adding dynamic data to the Adaptive Card is that straightforward! We now use the output of this Compose action in the next Action. The Microsoft Teams action “Post adaptive card and wait for a response”. You can configure this action by posting it to a Teams channel or as a direct chat to a person. In this use case I choose the latter. We will post as the Flow bot, to a chat between the recipient. To chat with the recipient, select the email address from the output of the user retrieval action.

Shows the Power Automate action Post adaptive card and wait for a response.
Post Adaptive Card to a Teams Chat

Just as an Approval Flow this action will wait until the submit action is performed on the user side. This corresponds with the Action.Submit action of the Adaptive Card. As we do not need any data from the Adaptive Card, we then just add the next Action into the Cloud Flow. Update the Task to set the Activity Status to Completed.

Shows the Power Automate action to update the Task to completed
Complete the Task

Conclusion

That’s it! A basic Adaptive Card to get you going. See below for the end result in action.

Shows an animated gif of a Model-Driven App where a task is created. This task gets posted to a Teams Chat as an Adaptive Card. From this Adaptive Card the Task gets completed. Helping people stay in their flow of work, instead of opening the Model-Driven App.
Adaptive Card to complete Task

You can now add extra text, fields or actions to this Card to make it your own. An excellent resource for more information is on the site of Microsoft MVP Tomasz Poszytek called Adaptive Cards – the ultimate guide. And of course, you can add extra business logic to the Cloud Flow. For instance, you might only want to trigger the Cloud Flow if the Regarding is of a certain type, or you can add your own Task Types. The possibilities are endless!

I hope this blogpost helps you see that Adaptive Cards are powerful and not so daunting as you would think. Feel free to let me know if this helps or if you have any questions.

Leave a Reply

Your email address will not be published. Required fields are marked *