从自定义提示转发消息到另一个对话框

时间:2017-06-05 08:30:57

标签: c# botframework

我正在使用this自定义类来制作自定义提示。

我修改了tryParse方法。如果用户没有选择任何选项,我想将消息转发到第一个Dialog。

代码:

   var promptOptions = new CancelablePromptOptions<string>(MyDictionary.ChooseOneOfTheFollowingOptions, cancelPrompt: "cancel", options: MyHelper.GetOptios(), promptStyler: PromptStyler);
            CancelablePromptChoice<string>.Choice(context, OptionSelected, promptOptions);

我正在尝试覆盖CancelablePromptOptions类中的TryParse函数:

   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);
        }

请注意代码中的MyFirstDialog。我想用当前消息重新创建第一个对话框。

目标:如果用户选择了一些存储更多选项的Dialog,并且第一个“choose”无效,我想重新创建MyFirstDialog。

有什么想法吗?

编辑:

MyFirstDialog是我从Messages控制器调用的第一个IDialog。

await Conversation.SendAsync(activity, () => new MyFirstDialog());

我从MyFirstDialog调用当前的IDialog:

context.Call(new CurrentDialog(), CurrentDialog.HandleOptions);

1 个答案:

答案 0 :(得分:1)

以下是关于如何返回初始对话框的示例,从最低级别开始。

CancelablePromptChoice 代码:

在这里你让基本实现执行“TryParse”,但是如果它不匹配你将处理它(通过返回true并保持值),避免重试

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 代码:

在此代码中,您将在OptionSelected中处理默认(T)回复(这是在提示后此对话框恢复时调用的方法)。通过执行context.Done<string>(null);,您将结束此对话框并返回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 代码:

所以最后在你的MyFirstDialog中你必须使用resume方法处理来自CurrentDialog的返回:

// 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));
    }
}