Reputation: 892
I'm using this custom class to make custom prompt.
I modified tryParse method. I would like to forward message to the first Dialog if user does not choose any option.
Code :
var promptOptions = new CancelablePromptOptions<string>(MyDictionary.ChooseOneOfTheFollowingOptions, cancelPrompt: "cancel", options: MyHelper.GetOptios(), promptStyler: PromptStyler);
CancelablePromptChoice<string>.Choice(context, OptionSelected, promptOptions);
I'm trying to override TryParse function in CancelablePromptOptions class :
protected override bool TryParse(IMessageActivity message, out T result)
{
if (IsCancel(message.Text))
{
result = default(T);
return true;
}
bool b = base.TryParse(message, out result);
if (!b)
Conversation.SendAsync(message, () => new MyFirstDialog());
return base.TryParse(message, out result);
}
Notice MyFirstDialog from code. I would like to recreate first dialog with the current message.
Goal : If user choose some Dialog where more options are stored and if the first "choose" is not valid, i would like to recreate MyFirstDialog.
Any idea ?
Edit :
MyFirstDialog is the first IDialog i'm calling from Messages controller.
await Conversation.SendAsync(activity, () => new MyFirstDialog());
I'm calling current IDialog from MyFirstDialog :
context.Call(new CurrentDialog(), CurrentDialog.HandleOptions);
Upvotes: 0
Views: 325
Reputation: 14589
Here is an example on how to go back to your initial dialog, starting for the lowest level.
CancelablePromptChoice code:
Here you let the basic implementation do the "TryParse", but if it's not matching you will handle it (by returning true and keeping the value), avoiding the retry
protected override bool TryParse(IMessageActivity message, out T result)
{
if (IsCancel(message.Text))
{
result = default(T);
return true;
}
var parsingTriedSucceeded = base.TryParse(message, out result);
// here you know if you found one of the options or not, and if not you override
if (!parsingTriedSucceeded)
{
result = (T)Convert.ChangeType(message.Text, typeof(T));
return true;
}
else
{
return parsingTriedSucceeded;
}
}
CurrentDialog code:
In this code you will handle your default(T) reply in the OptionSelected (which is the method called when this dialog is resuming after your prompt). By doing a context.Done<string>(null);
you will end this dialog and go back to MyFirstDialog
[Serializable]
public class CurrentDialog : IDialog<string>
{
public async Task StartAsync(IDialogContext context)
{
var promptOptions = new CancelablePromptOptions<string>(MyDictionary.ChooseOneOfTheFollowingOptions, cancelPrompt: "cancel", options: MyHelper.GetOptions(), promptStyler: PromptStyler);
CancelablePromptChoice<string>.Choice(context, OptionSelected, promptOptions);
}
private async Task OptionSelected(IDialogContext context, IAwaitable<string> result)
{
var chose = await result;
string answer = chose.ToString();
switch (answer)
{
case HelpEnumerator.Agenda:
await EventHelper.GetEventAgenda(context);
context.Done<string>(null);
break;
case HelpEnumerator.Register:
context.Call(new RegistrationDialog(), RegistrationDialog.Resume);
context.Done<string>(null);
break;
case HelpEnumerator.Speakers:
await EventHelper.GetSpeakers(context);
context.Done<string>(null);
break;
case HelpEnumerator.Tickets:
await EventHelper.GetTickets(context);
context.Done<string>(null);
break;
default:
context.Done(answer);
break;
}
}
}
MyFirstDialog code:
So finally in your MyFirstDialog you have to handle this return from the CurrentDialog, using the resume method:
// Somewhere in your logic...
context.Call(new CurrentDialog(), ResumeAfterCurrentDialog);
// On your class:
private async Task ResumeAfterCurrentDialog(IDialogContext context, IAwaitable<string> result)
{
// You are entering here after "context.Done(...)" in the CurrentDialog. To know the "result" value, take a look at what in the OptionSelected in CurrentDialog => it can be null for the options of the list, or the value in "answer" if it's not one of the options
// So we only have to test if it's not null, and then send the message again to the bot by using the "context.Activity" value
var resultText = await result;
if (resultText != null)
{
// Send the message again. It's already the message stored in context.Activity ;)
IMessageActivity msg = (IMessageActivity)context.Activity;
await this.MessageReceivedAsync(context, new AwaitableFromItem<IMessageActivity>(msg));
}
}
Upvotes: 1