I'm using Bot framework V4.3, I have been using adaptive card in waterfall dialog, to get user information, I would want to get values once user clicks submit button and also I would like to go back to previous step if user click back button.
Here is how my adaptive card looks like
I have tried the solution given by @mdrichardson in Stack Overflow But the adaptive card re-prompts again.
And the below code help us to go back to previous step but how to implement it to back button of adaptive card.
stepContext.ActiveDialog.State["stepIndex"] =(int)stepContext.ActiveDialog.State["stepIndex"] - 2;
Adding adaptive card to dialog. I had even used TextPrompt instead of ChoicePrompt
AddDialog(new ChoicePrompt("AdaptiveCardPrompt") { Style = ListStyle.None });
This is how I'm displaying adaptive card. My adaptive card is in Json format
cardAttachment = CreateAdaptiveCardAttachment();
return await stepContext.PromptAsync("AdaptiveCardPrompt",
new PromptOptions
{
Prompt = (Activity)MessageFactory.Attachment(new Attachment
{
ContentType = AdaptiveCard.ContentType,
Content = cardAttachment.Content
}),
}, cancellationToken);
Kindly help me in solving this issue. Thank you in advance
Edit from Botframework Support: Please do not use the code block below. It only works in Emulator. Instead, use:
if (string.IsNullOrWhiteSpace(activity.Text) && activity.Value != null)
{
activity.Text = JsonConvert.SerializeObject(activity.Value);
}
Edit 1: @mdrichardson Here is how I have setup the dialog call
public static async Task Run(this Dialog dialog, ITurnContext turnContext,IStatePropertyAccessor<DialogState> accessor, CancellationToken cancellationToken = default(CancellationToken))
{
var dialogSet = new DialogSet(accessor);
dialogSet.Add(dialog);
var dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken);
// Ensure that message is a postBack (like a submission from Adaptive Cards)
if (dialogContext.Context.Activity.GetType().GetProperty("ChannelData") != null)
{
var channelData = JObject.Parse(dialogContext.Context.Activity.ChannelData.ToString());
if (channelData.ContainsKey("postBack"))
{
var postbackActivity = dialogContext.Context.Activity;
// Convert the user's Adaptive Card input into the input of a Text Prompt
// Must be sent as a string
postbackActivity.Text = postbackActivity.Value.ToString();
await dialogContext.Context.SendActivityAsync(postbackActivity);
}
}
var results = await dialogContext.ContinueDialogAsync(cancellationToken);
if (results.Status == DialogTurnStatus.Empty)
{
await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
}
}
And in OnTurnAsync
method
if (turnContext.Activity.Type == ActivityTypes.Message)
{
await Dialog.Run(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
}
Edit 2 : I modified the code and I was able to go to next waterfall step. But I'm facing another issue here. Next prompt is not getting displayed but I can see it in Log This is how it shows in Emulator
Once user clicks the button control lands in MoreInfoAsync
method
private async Task<DialogTurnResult> MoreInfoAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var goback = JObject.Parse(stepContext.Result.ToString());
stepContext.Values["AdaptiveCardDetails"] = stepContext.Result.ToString();
if (goback.ContainsKey("goBack"))
{
return await stepContext.ReplaceDialogAsync(InitialDialogId);
}
// stepContext.ActiveDialog.State["stepIndex"] = (int)stepContext.ActiveDialog.State["stepIndex"] - 2;
else
return await stepContext.PromptAsync("MoreInfo", new PromptOptions { Prompt = MessageFactory.Text("Tell Me more.") }, cancellationToken);
}
I would like to go to initial dialog so I'm using ReplaceDialogAsync
.
MoreInfo
dialog is not displayed in emulator but its shown in log
Edit 3: Here is the complete code of waterfall steps
// This array defines how the Waterfall will execute.
var waterfallSteps = new WaterfallStep[]
{
ChoiceAsync,
CardAsync,
MoreInfoAsync,
ConfirmAsync
};
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
AddDialog(new ChoicePrompt("ChoiceType"));
AddDialog(new TextPrompt("AdaptiveCardPrompt"));
AddDialog(new TextPrompt("MoreInfo"));
InitialDialogId = nameof(WaterfallDialog);
private async Task<DialogTurnResult> ChoiceAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
options = new PromptOptions()
{
Prompt = MessageFactory.Text("Select the Choice"),
RetryPrompt = MessageFactory.Text("That was not a valid choice."),
Choices = GetChoices(),
Style = ListStyle.HeroCard
};
return await stepContext.PromptAsync("ChoiceType", options, cancellationToken);
}
private async Task<DialogTurnResult> CardAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var cardAttachment = new Attachment();
stepContext.Values["leaveType"] = stepContext.Result.ToString();
cardAttachment = CreateAdaptiveCardAttachment();
return await stepContext.PromptAsync("AdaptiveCardPrompt",
new PromptOptions
{
Prompt = (Activity)MessageFactory.Attachment(new Attachment
{
ContentType = AdaptiveCard.ContentType,
Content = cardAttachment.Content,
}),
}, cancellationToken);
}
private async Task<DialogTurnResult> MoreInfoAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var goback = JObject.Parse(stepContext.Result.ToString());
stepContext.Values["AdaptiveCardDetails"] = stepContext.Result.ToString();
if (goback.ContainsKey("goBack"))
{
return await stepContext.ReplaceDialogAsync(InitialDialogId);
}
else return await stepContext.PromptAsync("MoreInfo", new PromptOptions { Prompt = MessageFactory.Text("Tell Me more.") }, cancellationToken);
}
private async Task<DialogTurnResult> ConfirmAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["MoreInfo"] = stepContext.Result;
//As of now I wouldn't perform any task here so I'll end
return await stepContext.EndDialogAsync();
}
stepContext.Result
has yourgo back
value (whatever value you set the card to send when clicking back) – mdrichardsonReplaceDialogAsync
is a good idea and you're using it correctly. Tough to say why it isn't being shows. Can you either paste all of your code for theMoreInfo
dialog or a link to your repo? Can you also describe your new issue a little more? Is it just that the dialog isn't restarting? – mdrichardsonMoreInfo
dialog if you see emulator snapshot after submitting the submit button the control goes toMoreInfo
but inMoreinfo
the prompt that im trying to return is not getting displayed in the emulator output screen. But I can see "Tell me more" in emulator log.Why isn't the same getting displayed to user on output. Where have I made a mistake – Gags08MoreInfoAsync
looks fine, so the problem is likely elsewhere. Do you have something likeAddDialog(new TextPrompt("MoreInfo"));
? If you can link to all of your code it would make this much easier to debug. – mdrichardsonawait dialogContext.Context.SendActivityAsync(postbackActivity);
inRun()
. Try deleting that, since you don't really need to send that. I've uploaded my code to a github repo so you can take a look and try to find differences. Again, this would be significantly easier to debug with all of your code. – mdrichardson