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:

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:

  1. The user selects the message extension to invoke the dialog.

  2. The user configures the poll with the dialog.

  3. 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.

  4. 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.
  5. 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.

User attribution bots

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