首页 > 解决方案 > Botframework v4: waterfall stepcontext result. How to simplify?

问题描述

I have this dialog that either number prompt the user or confirm prompt the user depending on a property. It then check the type of waterfall stepcontext result if it is decimal or bool. It is working as intented but i think it is overcomplicated and prone to error.

Is there a better way to do this? Here is the code:

public class LoanCalculator : WaterfallDialog
{
    public LoanCalculator(string dialogId, IEnumerable<WaterfallStep> steps = null)
        : base(dialogId, steps)
    {
        AddStep(async (stepContext, cancellationToken) =>
        {
            // check if the property has a price
            var userstate = await (stepContext.Context.TurnState["BasicAccessors"] as BasicAccessors).BasicUserStateAccessor.GetAsync(stepContext.Context);

            // if zero, decimal prompt
            if (userstate.PropertyPrice == 0)
            {
                return await stepContext.PromptAsync(
                "numberPromptDecimal",
                new PromptOptions
                {
                    Prompt = MessageFactory.Text("Indicate price of property."),
                    RetryPrompt = MessageFactory.Text("Please enter a valid amount."),
                });
            }
            else
            {
                // if not zero bool prompt confirm if user wants to change its value or not
                return await stepContext.PromptAsync(
                "confirmPrompt",
                new PromptOptions
                {
                    Prompt = MessageFactory.Text($"Property price is {userstate.PropertyPrice}. Is this correct?"),
                });
            }
        });

        AddStep(async (stepContext, cancellationToken) =>
        {
            var userstate = await (stepContext.Context.TurnState["BasicAccessors"] as BasicAccessors).BasicUserStateAccessor.GetAsync(stepContext.Context);

            // if decimal prompt
            if (stepContext.Result is decimal)
            {
                stepContext.Values["price"] = Convert.ToDecimal(stepContext.Result);
                return await stepContext.NextAsync();
            }
            // if bool prompt
            else if (stepContext.Result is bool)
            {
                // if user does not want to change value
                if ((bool)stepContext.Result)
                {
                    stepContext.Values["price"] = userstate.PropertyPrice;
                    return await stepContext.NextAsync();
                }
                // if user want to change value, make value zero and restart dialog
                else
                {
                    userstate.PropertyPrice = 0;
                    return await stepContext.ReplaceDialogAsync(Id);
                }
            }
            else
            {
                // i dont know what to do with this so i just restart dialog
                return await stepContext.ReplaceDialogAsync(Id);
            }
        });

        AddStep(async (stepContext, cancellationToken) =>
        {
            // if stepcontext values is not equals to null
            if (!stepContext.Values["price"].Equals(null))
            {
                return await stepContext.PromptAsync(
                "numberPromptDecimal",
                new PromptOptions
                {
                    Prompt = MessageFactory.Text("Indicate amount of loan."),
                    RetryPrompt = MessageFactory.Text("Please enter a valid amount."),
                });
            }
            else
            {
                // again dont know what to odo with this
                await stepContext.Context.SendActivityAsync(MessageFactory.Text($"oops"));
                return await stepContext.ReplaceDialogAsync(Id);
            }
        });

        AddStep(async (stepContext, cancellationToken) =>
        {
            // continue
        });
    }

    public static string Id = "loanCalculator";

    public static LoanCalculator Instance { get; } = new LoanCalculator(Id);
}

标签: c#botframework

解决方案


我建议分成两个可能的子对话框。而不是访问stepContext.Values["price"],这些子对话框可以通过传递价格将价格返回到顶级对话框EndDialogAsync

我的其余答案会挑剔您没有特别询问的有关您的代码的事情。

由于您要求提供建议,因此我应该提到 Bot Framework 示例很少扩展WaterfallDialog. 如果您想创建自己的对话框类,则继承自ComponentDialog并具有 aWaterfallDialog作为其起始组件会更加标准,但在您的情况下,我不确定您是否需要自定义对话框类。而且,如果您确实进行了扩展WaterfallDialog,那么在构造函数中具有相同的两个参数会有点奇怪,因为您肯定不希望将任何步骤传递给它。为什么不这样做呢?

public LoanCalculator() : base(Id, null)

推荐阅读