Search code examples
c#.netbotframeworkadaptive-cards

AdaptiveCard prompt inside a WaterfallDialog keeps showing over and over


I'm testing an Adaptive Card that only has 2 elements: a text and an action:

enter image description here

Its definition is this:

{
    "type": "AdaptiveCard",
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.2",
    "body": [
        {
            "type": "TextBlock",
            "text": "This is a test",
            "wrap": true
        },
        {
            "type": "Input.ChoiceSet",
            "choices": [
                {
                    "title": "Option 1",
                    "value": "1"
                },
                {
                    "title": "Option 1",
                    "value": "2"
                }
            ],
            "placeholder": "Select a option",
            "id": "option"
        },
        {
            "type": "ActionSet",
            "actions": [
                {
                    "type": "Action.Submit",
                    "title": "Next"
                }
            ]
        }
    ]

}

I want to show this card as part of a prompt inside a dialog of a WaterfallDialog, so I do this:

public class MyDialog : ComponentDialog
{
    public MyDialog(string id) : base(id)
    {
        //...
        AddDialog(new ChoicePrompt("Test"));
        //...
    }

    private async Task<DialogTurnResult> TestStep(WaterfallStepContext stepcontext, CancellationToken cancellationtoken)
    {
        // Loads the card from the JSON I showed above
        var card = await LoadAdaptiveCard("MyCard.json");
        return await stepcontext.PromptAsync("Test", new PromptOptions()
        {
            Prompt = (Activity)MessageFactory.Attachment(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = JObject.FromObject(card),
            }),         
            Style = ListStyle.None,
        }, cancellationtoken);
    }
}

The prompt shows OK, but after I click on "Next", the card is showed again. It seems like it's stuck on it and never goes to the next dialog step.

I would like the Next button to be like a "Submit" button that proceeds to the next step. What's wrong with my code?

Notice

The real Adaptive Card is this one: enter image description here

I posted a simpler one for the sake of simplicity.


Solution

  • In certain situations, a choice input can be used to automatically recognize a choice from card action data. You can see here how the incoming activity's value is also used as input instead of just the activity's text.

    if (string.IsNullOrEmpty(dc.Context.Activity.Text) && dc.Context.Activity.Value != null)
    {
        input = dc.Context.Activity.Value;
    }
    

    However, you're not using a choice input, you're using a choice prompt. Of course, there's nothing wrong with that. Prompts are exactly what you should be using since you're using a waterfall dialog and not an adaptive dialog. It's just important to keep in mind that prompts are somewhat simpler than inputs, and in most cases they'll only account for the incoming activity's text and not the value.

    That explains why your prompt isn't recognizing the card's action data, but there's a bigger problem to consider. It doesn't matter whether you're using a prompt or an input because they're both wrong in this case. Choice prompts/inputs are only meant to recognize one singular choice, so they could potentially work for the minimal sample card you've provided, but they can't possibly work for the actual card you want to use. Your actual card has multiple choice sets, and there's no way for a choice prompt or a choice input to account for multiple choices made at the same time.

    Given that choice prompts aren't the right choice for you, you still need to know what to do instead. You say you want to continue on to the next waterfall step, and that's easy. In order to continue to the next waterfall step instead of repeating the prompt, don't even use a prompt. Just send the Adaptive Card on its own as a normal activity and then return an end-of-turn result. If the user enters text instead of clicking the button, you'll have to handle that somehow in the next waterfall step.

    Supposing that's not quite satisfactory and you actually want to do more than just make sure the waterfall dialog continues, you may still need some kind of prompt. Prompts make sure the dialog doesn't continue until you get the information you need, and in your case you want the information from the Adaptive Card. There are a few options for you:

    1. Make your own special Adaptive Card prompt
    2. Use an Adaptive Card prompt someone else has made
    3. Use a text prompt

    That third option may sound strange, but text prompts are useful because they'll accept any string by default, and as with any prompt you can supply your own custom validator to make sure the data is in the format you want. I've given more information about this in the "Adaptive Cards in Dialogs" section of my blog post: https://blog.botframework.com/2019/07/02/using-adaptive-cards-with-the-microsoft-bot-framework/