0

Im trying to parse the adaptive card using Waterfallstep in the Virtual Assistant template , its not waiting for the user input to be filled in the card. The below code worked when I used the Multiprompt template but its not working in Virtual Assistant template.

private async Task<DialogTurnResult> 
StartTheDialogAsync(WaterfallStepContext sc, CancellationToken 
cancellationToken)
{
 var attachment = CreateAdaptiveCardAttachment(cards);
 var replyMessage = sc.Context.Activity.CreateReply();
 replyMessage.Attachments.Add(attachment);
 await sc.Context.SendActivityAsync(replyMessage, cancellationToken);
 return new DialogTurnResult(DialogTurnStatus.Waiting);
 }
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445

1 Answers1

2

There's nothing in the Bot Framework that causes a dialog to wait for user input after sending an adaptive card. My guess is that it's working in the MultiPrompt sample coincidentally because of how the sample is coded.

The two ways to force a wait are:

  1. Send a blank text prompt directly after the adaptive card
  2. Send the adaptive card as an attachment to a blank text prompt

See any of these answers for more details:

You basically need three pieces of code:

private async Task<DialogTurnResult> DisplayCardAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // Create the Adaptive Card
    var cardPath = Path.Combine(".", "AdaptiveCard.json");
    var cardJson = File.ReadAllText(cardPath);
    var cardAttachment = new Attachment()
    {
        ContentType = "application/vnd.microsoft.card.adaptive",
        Content = JsonConvert.DeserializeObject(cardJson),
    };

    // Create the text prompt
    var opts = new PromptOptions
    {
        Prompt = new Activity
        {
            Attachments = new List<Attachment>() { cardAttachment },
            Type = ActivityTypes.Message,
            Text = "waiting for user input...", // You can comment this out if you don't want to display any text. Still works.
        }
    };

    // Display a Text Prompt and wait for input
    return await stepContext.PromptAsync(nameof(TextPrompt), opts);
}

private async Task<DialogTurnResult> HandleResponseAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // Do something with step.result
    // Adaptive Card submissions are objects, so you likely need to JObject.Parse(step.result)
    await stepContext.Context.SendActivityAsync($"INPUT: {stepContext.Result}");
    return await stepContext.NextAsync();
}

The validator

private async Task<bool> CardValidator(PromptValidatorContext<string> promptContext, CancellationToken cancellationToken)
        {
            
            var activity = promptContext.Context.Activity;

            if (string.IsNullOrWhiteSpace(activity.Text) && activity.Value != null)
            {
                activity.Text = JsonConvert.SerializeObject(activity.Value);
                return true;
            }
            return false;
        }

and

var activity = turnContext.Activity;

if (string.IsNullOrWhiteSpace(activity.Text) && activity.Value != null)
{
    activity.Text = JsonConvert.SerializeObject(activity.Value);
}

Again, read the linked answers for more details.

The Memebot
  • 3,199
  • 1
  • 16
  • 21
mdrichardson
  • 7,141
  • 1
  • 7
  • 21