首页 文章

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

提问于
浏览 848
0

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

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


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

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

我无法调用我制作的自定义提示 . 任何帮助表示赞赏,谢谢 .

2 回答

  • 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

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

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

    这个怎么运作:

    • 提示用户输入

    • 等待照片

    • 验证输入

    • 如果有效,则调用context.Done或如果失败则向用户显示消息并再次等待输入 .

    当我创建对话框时,我提交了一个验证结果的验证器类,这是我创建的用于验证特定长度的文本输入的验证器类 . 它不是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

相关问题