Respond to the dialog submit action
Important
The code samples in this section are based on v4.6 and later versions of the Bot Framework SDK. If you're looking for documentation for earlier versions, see the Message Extensions - v3 SDK section in the Resources folder of the documentation.
This document guides you on how your app responds to the action commands, such as user's dialog (referred as task module in TeamsJS v1.x) submit action.
After a user submits the dialog, your web service receives a composeExtensions/submitAction
invoke message with the command ID and parameter values. Your app has five seconds to respond to the invoke.
You have the following options to respond:
- No response: Use the submit action to trigger a process in an external system and not provide any feedback to the user. It's useful for long-running processes and to provide feedback alternately. For example, you can give feedback with a proactive message.
- Another dialog: You can respond with additional dialog as part of a multi-step interaction.
- Card response: You can respond with a card that the user can interact with or insert into a message.
- Adaptive Card from bot: Insert an Adaptive Card directly into the conversation.
- Request the user to authenticate.
- Request the user to provide additional configuration.
If the app doesn't respond within five seconds, the Teams client retries the request twice before it sends an error message Unable to reach the app. If the bot replies after the timeout, the response is ignored.
Note
- The app must defer any long-running actions after the bot replies to the invoke request. The long-running action results can be delivered as a message.
- Your app has five seconds to respond to the invoke message.
For authentication or configuration, after the user completes the process, the original invoke is resent to your web service. The following table shows which types of responses are available, based on the invoke location commandContext
of the message extension:
Response Type | Compose | Command bar | Message |
---|---|---|---|
Card response | ✔️ | ✔️ | ✔️ |
Another dialog | ✔️ | ✔️ | ✔️ |
Bot with Adaptive Card | ✔️ | ❌ | ✔️ |
No response | ✔️ | ✔️ | ✔️ |
Note
- When you select Action.Submit through ME cards, it sends invoke activity with the name composeExtensions, where the value is equal to the usual payload.
- When you select Action.Submit through conversation, you receive message activity with the name onCardButtonClicked, where the value is equal to the usual payload.
If the app contains a conversational bot, install the bot in the conversation, and then load the dialog. The bot is useful to get more context for the dialog. To install conversational bot, see Request to install your conversational bot.
The submitAction invoke event
Examples of receiving the invoke message are as follows:
protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionSubmitActionAsync(
ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) {
//code to handle the submit action
}
Respond with a card inserted into the compose message area
The most common way to respond to the composeExtensions/submitAction
request is with a card inserted into the compose message area. The user submits the card to the conversation. For more information on using cards, see cards and card actions.
protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionSubmitActionAsync(
ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
{
var response = new MessagingExtensionActionResponse
{
ComposeExtension = new MessagingExtensionResult
{
AttachmentLayout = "list",
Type = "result",
},
};
var createCardData = ((JObject)action.Data).ToObject<CreateCardData>();
var card = new HeroCard
{
Title = createCardData.Title,
Subtitle = createCardData.Subtitle,
Text = createCardData.Text,
};
var attachments = new List<MessagingExtensionAttachment>();
attachments.Add(new MessagingExtensionAttachment
{
Content = card,
ContentType = HeroCard.ContentType,
Preview = card.ToAttachment(),
});
response.ComposeExtension.Attachments = attachments;
return response;
}
Respond with another dialog
You can select to respond to the submitAction
event with additional dialog. It's useful in the following scenarios:
- Collect large amounts of information.
- Dynamically change the information collection based on user input.
- Validate the information submitted by the user and resend the form with an error message if something is wrong.
The method for response is the same as responding to the initial fetchTask
event. If you're using the Bot Framework SDK the same event triggers for both submit actions. To make this work, you must add logic that determines the correct response.
Bot response with Adaptive Card
Note
The prerequisite to get the bot response with an Adaptive Card is that you must add the
bot
object to your app manifest, and define the required scope for the bot. Use the same ID as your message extension for your bot.Outlook doesn't support bot response with Adaptive Card.
You can also respond to the submitAction
by inserting a message with an Adaptive Card into the channel with a bot. The user can preview the message before submitting it. It's useful in scenarios where you gather information from the users before creating an Adaptive Card response, or when you update the card after someone interacts with it.
The following scenario shows how the app Polly configures a poll without including the configuration steps in the channel conversation:
To configure the poll:
The user selects the message extension to invoke the dialog.
The user configures the poll with the dialog.
When the user submits the dialog, the app uses the information provided to build the poll as an Adaptive Card and sends it as a
botMessagePreview
response to the client.The user can then preview the Adaptive Card message before the bot inserts it into the channel. If the app isn't a member of the channel, select
Send
to add it.Note
- The users can also select to
Edit
the message, which returns them to the original dialog. - Interaction with the Adaptive Card changes the message before sending it.
- The users can also select to
After the user selects
Send
, the bot posts the message to the channel.
Respond to initial submit action
Your dialog must respond to the initial composeExtensions/submitAction
message with a preview of the card that the bot sends to the channel. The user can verify the card before sending, and try to install your bot in the conversation if the bot is already installed.
protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionSubmitActionAsync(
ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
{
dynamic createCardData = ((JObject) action.Data).ToObject(typeof(JObject));
var response = new MessagingExtensionActionResponse
{
ComposeExtension = new MessagingExtensionResult
{
Type = "botMessagePreview",
ActivityPreview = MessageFactory.Attachment(new Attachment
{
Content = new AdaptiveCard("1.0")
{
Body = new List<AdaptiveElement>()
{
new AdaptiveTextBlock() { Text = "FormField1 value was:", Size = AdaptiveTextSize.Large },
new AdaptiveTextBlock() { Text = Data["FormField1"] as string }
},
Height = AdaptiveHeight.Auto,
Actions = new List<AdaptiveAction>()
{
new AdaptiveSubmitAction
{
Type = AdaptiveSubmitAction.TypeName,
Title = "Submit",
Data = new JObject { { "submitLocation", "messagingExtensionFetchTask" } },
},
}
},
ContentType = AdaptiveCard.ContentType
}) as Activity
}
};
return response;
}
The botMessagePreview send and edit events
Your message extension must respond to two new types of the composeExtensions/submitAction
invoke, where value.botMessagePreviewAction = "send"
and value.botMessagePreviewAction = "edit"
.
protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionBotMessagePreviewEditAsync(
ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
{
//handle the event
}
protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionBotMessagePreviewSendAsync(
ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
{
//handle the event
}
Respond to botMessagePreview edit
If the user edits the card before sending, by selecting Edit, you receive a composeExtensions/submitAction
invoke with value.botMessagePreviewAction = edit
. Respond by returning the dialog you sent, in response to the initial composeExtensions/fetchTask
invoke that began the interaction. The user can start the process by reentering the original information. Use the available information to update the dialog so that the user doesn't need to fill out all information from scratch.
For more information on responding to the initial fetchTask
event, see responding to the initial fetchTask
event.
Respond to botMessagePreview send
After the user selects the Send, you receive a composeExtensions/submitAction
invoke with value.botMessagePreviewAction = send
. Your web service must create and send a message with the Adaptive Card to the conversation, and also reply to the invoke.
protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionBotMessagePreviewSendAsync(
ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
{
var activityPreview = action.BotActivityPreview[0];
var attachmentContent = activityPreview.Attachments[0].Content;
var previewedCard = JsonConvert.DeserializeObject<AdaptiveCard>(attachmentContent.ToString(),
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
previewedCard.Version = "1.0";
var responseActivity = Activity.CreateMessageActivity();
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = previewedCard
};
responseActivity.Attachments.Add(attachment);
// Attribute the message to the user on whose behalf the bot is posting
responseActivity.ChannelData = new {
OnBehalfOf = new []
{
new
{
ItemId = 0,
MentionType = "person",
Mri = turnContext.Activity.From.Id,
DisplayName = turnContext.Activity.From.Name
}
}
};
await turnContext.SendActivityAsync(responseActivity);
return new MessagingExtensionActionResponse();
}
User attribution for bots messages
In scenarios where a bot sends messages on behalf of a user, attributing the message to that user helps with engagement and display a more natural interaction flow. This feature lets the bot show messages on behalf of a user with the user's name displayed in the Adaptive Card response header.
The following images display an Adaptive Card message sent by a bot. The left-side image is without user attribution and the right-side image is with user attribution. The image with user attribution displays the name of the user in the format: username via bot (Megan Bowen via Poll) in the Adaptive Card header.
To use the user attribution in teams, you must add the OnBehalfOf
mention entity to ChannelData
in your Activity
payload that is sent to Teams.
// Attribute the message to the user on whose behalf the bot is posting
responseActivity.ChannelData = new {
OnBehalfOf = new []
{
new
{
ItemId = 0,
MentionType = "person",
Mri = turnContext.Activity.From.Id,
DisplayName = turnContext.Activity.From.Name
}
}
};
Details of OnBehalfOf
entity schema
The following section is a description of the entities in the OnBehalfOf
Array:
Field | Type | Description |
---|---|---|
itemId |
Integer | Describes identification of the item. Its value must be 0 . |
mentionType |
String | Describes the mention of a "person". |
mri |
String | Message resource identifier (MRI) of the person on whose behalf the message is sent. Message sender name would appear as "<user> through <bot name>." |
displayName |
String | Name of the person. Used as fallback in case name resolution is unavailable. |
Code sample
Sample name | Description | .NET | Node.js | Manifest |
---|---|---|---|---|
Teams message extension action | This sample shows how to define action commands, create dialog, and respond to dialog submit action. | View | View | View |
Message extension action preview | This sample shows how to use action preview in Messaging Extensions using Bot Framework v4. | View | View | View |
Teams message extension search | This sample shows how to build a Search-based Message Extension. It searches NuGet packages and displays the results in search based messaging extension. | View | View | View |
Next Step
See also
Platform Docs