【问题标题】:Bot Framework PromptDialog not asking first promptBot Framework PromptDialog 不询问第一个提示
【发布时间】:2018-11-09 17:24:42
【问题描述】:

我正在学习 Microsoft Bot Framework,因此我正在学习教程并处理一些示例对话框。我正在尝试编写一个计算器机器人。 (机器人要求一个整数、一个操作和另一个整数)。

但是,我无法让机器人真正询问用户的输入。如果用户在启动对话框后键入任何内容,则响应为$invalid need: expected Call, have Poll。我看到一些问题说你不能在同一个函数调用中使用提示符和context.Wait,但是我没有找到任何关于如何处理这个问题的信息。

public class CalculatorDialog : IDialog<object>
{
    protected readonly String[] operators = { "+", "-", "*", "/" };
    private long Left { get; set; }
    private long Right {get; set; }
    private String Operator { get; set; }

    public async Task StartAsync(IDialogContext context)
    {
        context.Wait(Calculate);
    }

    private async Task Calculate(IDialogContext context, 
                                 IAwaitable<IMessageActivity> result)
    {
        await result;

        PromptDialog.Number(
            context,
            async (ctx, lhs) => { Left = await lhs; },
            "Left hand side"
        );

        PromptDialog.Choice<string>(
            context,
            async (ctx, op) => { Operator = await op; },
            new PromptOptions<string>("Operator:", options: operators)
        );

        PromptDialog.Number(
            context,
            async (ctx, rhs) => { Right = await rhs; },
            "Right hand side"
        );

        long res;
        switch (Operator) { /* res = Left Operator Right */}

        await context.PostAsync($"The result is: ${res}");
    }
}

调用这个的代码是

switch (activity.Text)
{
    case "math":
        context.Call(new CalculatorDialog(), this.ResumeAfterSubDialog);
        break;
}

ResumeAferSubDialog 继续主循环。

【问题讨论】:

    标签: c# botframework


    【解决方案1】:

    在你的代码中,我发现你不断调用PromptDialog.NumberPromptDialog.Choice方法,你可以修改你的代码来执行/调用下一个PromptDialog在上一个Resume handler,下面的代码sn-p供大家参考。

    private async Task Calculate(IDialogContext context, IAwaitable<IMessageActivity> result)
    {
        await result;
    
        PromptDialog.Number(
            context,
            LeftReceivedAsync,
            "Left hand side"
        );
    }
    
    private async Task LeftReceivedAsync(IDialogContext context, IAwaitable<long> lhs)
    {
        Left = await lhs;
    
        PromptDialog.Choice<string>(
            context,
            OperatorReceivedAsync,
            new PromptOptions<string>("Operator:", options: operators)
        );
    }
    
    private async Task OperatorReceivedAsync(IDialogContext context, IAwaitable<string> op)
    {
        Operator = await op;
    
        PromptDialog.Number(
            context,
            RightReceivedAsync,
            "Right hand side"
        );
    }
    
    private async Task RightReceivedAsync(IDialogContext context, IAwaitable<long> rhs)
    {
        Right = await rhs;
    
        long res;
    
        //switch (Operator) { /* res = Left Operator Right */}
    
        await context.PostAsync($"The result is: ${res}");
    
    }
    

    注意:

    根据我的测试,PromptDialog.Choice 不适用于这些特殊字符 ("+", "-", "*", "/"),它不会将所选选项识别为可用选项,但让用户重试一次。

    测试图片1:

    如果可能,您可以提供不同的选项列表,例如:

    protected readonly String[] operators = { "add (+)", "subtract (-)", "multiply (*)", "divide (/)" };
    

    测试图片2:

    【讨论】:

    • 好的,那么每个方法只能有一个PromptDialog 调用吗?
    • can there only every be one PromptDialog call per method? @EdwardMinnix 嗨,你的意思是创建一个 PromptDialog 的实例,然后调用 .Number()。 Choice() 方法通过该实例对象?如果查看 PromptDialog 类的定义,可以发现 .Number().Choice() 方法被定义为 static,无需创建类实例即可调用。
    • 我的意思是我想知道如果我的代码中的错误之一是使用 .Number().Choice()以链式方式(都在同一个方法中),而不是像上面那样有一个方法链。
    • 据我所知,不建议在同一方法中一次一个地调用 PromptDialog.Number() 和 PromptDialog.Choice() 方法,正如您在问题中提到的那样,可能会导致异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 2019-09-24
    • 1970-01-01
    相关资源
    最近更新 更多