在BotFramework C#中循环提示,直到验证为止

时间:2018-02-01 12:12:04

标签: c# botframework

我尝试继承PromptString类并循环提示,直到用户提供正确的输入。

我编写了以下代码来验证用户是否指定了有效日期。

这是我的自定义提示类,我要验证用户是否输入了正确的日期,如果他输入了正确的日期,它应该只是退出对话框,否则它应该再次重新提示输入。< / p>

namespace CustomPromptDemo.Models
{
    public class CustomPrompt : PromptString
    { 
        public CustomPrompt(string Prompt = "Please enter a date", string Retry = "Please enter a valid date!!!", int RetryCount = 3) : base(Prompt, Retry, RetryCount)
            {

            }

        protected override IMessageActivity MakePrompt(IDialogContext context, string prompt, IReadOnlyList<string> options = null, IReadOnlyList<string> descriptions = null, string speak = null)
        {
            return base.MakePrompt(context, prompt, options, descriptions, speak);
        }

        bool ValidateIfDateOrNot(string Query)
        {
            try
            {
                DateTime date = default(DateTime);
                DateTimeModel model = DateTimeRecognizer.GetInstance().GetDateTimeModel(Culture.English);
                List<ModelResult> parsedResults = model.Parse(Query);

                var resolvedValue = (parsedResults.SelectMany(x => x.Resolution).FirstOrDefault().Value as List<Dictionary<string, string>>).SelectMany(x => x).Where(x => x.Key.Equals("value")).Select(y => y.Value).FirstOrDefault();

                return DateTime.TryParse(resolvedValue, out date);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        protected override async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> message)
        {
            IMessageActivity msg = await message;

            if (ValidateIfDateOrNot(msg.Text))
            {
                await context.PostAsync("Valid date!");
                context.Done<object>(null);
            }
            else
            {
                await context.PostAsync("Please enter a valid date!");
                await base.MessageReceivedAsync(context, message);
            }
        }
        protected override bool TryParse(IMessageActivity message, out string result)
        {
            return base.TryParse(message, out result);
        }
    }
}

这是我的RootDialog

    namespace CustomPromptDemo.Dialogs
    {
        [Serializable]
        public class RootDialog : IDialog<object>
        {
            public Task StartAsync(IDialogContext context)
            {
                context.Wait(MessageReceivedAsync);

                return Task.CompletedTask;
            }

            private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
            {
                CustomPrompt c = new CustomPrompt();
                c.
            }
        }
    }

我有多种方法可供选择,如下面的截图所示。

enter image description here

我无法调用我制作的自定义提示。 感谢任何帮助。谢谢。

3 个答案:

答案 0 :(得分:1)

您可以像使用PromptDialog.Text一样使用它,请参阅GitHub来源:

public class PromptDialog
{
    public static void Text(IDialogContext context, ResumeAfter<string> resume, string prompt, string retry = null, int attempts = 3)
    {
        var child = new PromptString(prompt, retry, attempts);
        context.Call<string>(child, resume);
    }

所以在你的情况下:

[Serializable]
public class RootDialog : IDialog<object>
{
    public Task StartAsync(IDialogContext context)
    {
        context.Wait(MessageReceivedAsync);

        return Task.CompletedTask;
    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
    {
        var prompt = new CustomPrompt();
        context.Call<string>(prompt, ResumeAfterPromptString);
    }

    private async Task ResumeAfterPromptString(IDialogContext context, IAwaitable<string> result)
    {
        // Do what you want here... But your customPrompt should return a string

        context.Done<object>(null);
    }
}

顺便说一句,您还必须使CustomPrompt可序列化:

[Serializable]
public class CustomPrompt : PromptDialog.PromptString

如果ValidateIfDateOrNot没问题,你应该返回你的字符串而不是null。

编辑:最后一件事,你应该看看GitHub项目中提供的关于你正在使用的识别器的样本,here,这是解析日期的一个很好的例子,就像你想要的那样

答案 1 :(得分:1)

我在我的机器人中构建了一些非常相似的东西,提示用户输入图像,然后如果他们没有输入有效图像则继续循环:

[Serializable]
public class PhotoInputDialog : IDialog<string>
{
    public ICustomInputValidator<IMessageActivity> Validator { get; private set; }

    public string InputPrompt { get; private set; }
    public string WrongInputPrompt { get; private set; }

    public static PhotoInputDialog Create
        (string inputPrompt, string wrongInputPrompt, ICustomInputValidator<IMessageActivity> validator)
    {
        return new PhotoInputDialog()
        { InputPrompt = inputPrompt, WrongInputPrompt = wrongInputPrompt, Validator = validator };
    }

    public async Task StartAsync(IDialogContext context)
    {
        await context.PostAsync(InputPrompt);
        context.Wait(InputGiven);
    }

    private async Task InputGiven(IDialogContext context, IAwaitable<IMessageActivity> result)
    {
        var message = await result;
        if (!Validator.IsValid(message))
        {
            await context.PostAsync(WrongInputPrompt);
            context.Wait(InputGiven);
        }
        else
            context.Done(message.Attachments.First().ContentUrl);
    }
}

工作原理:

  1. 提示用户输入
  2. 等待照片
  3. 验证输入
  4. 如果有效,则调用context.Done或如果失败则向用户显示消息并再次等待输入。
  5. 当我创建对话框时,我提交了一个用于验证结果的验证器类,这是我创建的用于验证特定长度的文本输入的验证器类。它不是100%必要的,但它现在很好并且可以重复使用:

    [Serializable()]
    public class TextCustomInputValidator : ICustomInputValidator<string>
    {
        private int MinLength, MaxLength;
        public TextCustomInputValidator(int minLength, int maxLength)
        {
            MinLength = minLength;
            MaxLength = maxLength;
        }
        public bool IsValid(string input)
        {
            return input.Length >= MinLength && input.Length <= MaxLength;
        }
    }
    

    在Bot框架中有很多不同的方法来做Bot,所以可能有其他方法可行。我想到的另一个问题是使用FormFlow,因为它有一个日期输入验证器:https://docs.botframework.com/en-us/csharp/builder/sdkreference/dc/db8/class_microsoft_1_1_bot_1_1_builder_1_1_form_flow_1_1_advanced_1_1_recognize_date_time.html

答案 2 :(得分:1)

您可以使用DateTimePrompt,或者如果您真的想进一步控制简单的TextPrompt并为其提供自定义验证器,则可以:

1,Maths,85

在对话框中,您可以启动提示,提供重试提示,以便在重试失败时显示单独的消息:

AddDialog(new DateTimePrompt(nameof(DateTimePrompt), DateTimePromptValidator));

如果您希望使用多种语言的日期来处理高级案件,我建议您看一下Microsoft的Recognizers-Text,该语言当前在LUIS:语言理解智能服务中提供预构建实体。