Universal Actions for Adaptive cards are a mechanism to handle user
interactions uniformly no matter where the user is accessing the Adaptive Card
from. It allows Bot developers to send the same Adaptive Cards to Microsoft
Teams, Outlook etc. without having to write redundant client specific code. As the Microsoft
docs state:
Universal Actions for Adaptive Cards evolved from developer feedback that
even though layout and rendering for Adaptive Cards was universal, action
handling was not. Even if a developer wanted to send the same card to
different places, they have to handle actions differently. Universal Actions
for Adaptive Cards brings the bot as the common backend for handling
actions.
https://docs.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/universal-actions-for-adaptive-cards/overview?tabs=mobile
In addition to these user interactions, there are couple of really useful
features delivered as part of Universal Actions. They are "User Specific
Views" and "Up to date cards"
User specific views:
By using user specific views, different users see different views on the card
depending on their identity and the actions they have taken. This was not the
case earlier when all users who viewed an Adaptive Card posted in a Teams
channel saw the same exact card. Lets see a quick example:
First lets talk about the refresh property. The property contains two
important values: action and userIds. When an adaptive card containing a
refresh property will load, first the Teams platform will check if the
current user viewing the Adaptive Card is present in the userIds property.
If they are, then an action will be sent to the bot containing the verb
mentioned in the verb property. We will have to write Bot Framework code which handles
this call from the Teams platform. As a response to this call, we can return
a new adaptive card which will only be visible to the current
user.
All other users viewing the Adaptive card who are not part of the userIds property will keep seeing a
shared common view of the base card.
Up to date cards:
With up to date cards, we can use the Bot Framework message update
functionality to update the user specific views in adaptive cards on the fly. This is so that the cards are updated to their latest state without the user having to reload the card.
Now that we have covered the different moving parts, let's see how we can put
all of this together in a code sample for a approving an asset in a Teams
channel:
1) A user starts the approval process by sending a command to the bot:
The user starting the approval request is the "Owner" of this asset. When the owner sends an approval request, an adaptive card with a "Approve" button will be shown to everyone in the Team who is
not the owner. Where as, the owner will see a view on the card which contains a list of users who have approved the request.
2) Approving the asset and refreshing the Adaptive Card with latest state:
Any user in the team can click on the approve button to approve the asset. Once they approve, they will be shown a
different card.
Owner will always see who approved the card. This will be kept up to date using
the message edit mechanism without the need to manually reload the card.
Now we come to the crux of the blog post. Whenever a user will click on the "Approve" button, or and Adaptive Card will load which contains a refresh property with the current user's userId, an adaptiveCard/action request will be sent to our bot. The request will contain information on the action such as the verb and the context in which the action occurred.
Out bot framework code will have to respond with the correct card depending on the action.
In the above code, when the approveClicked action occurs, we add the user approving the asset to our persistent storage and return a card to them thanking them for the approval.
When the refreshCard action occurs, it means that a user listed in the userIds property of a card is trying to view the card. So based on the identity of the user, we will return the correct card. This is used to show the owner of the card a list of users who have approved it.
Hope you found the post useful!
Full code sample of this blog post available on GitHub: https://github.com/vman/Universal.Actions