The TextPrompt mechanism in V4 is fine and can implement a variety of validation techniques because it uses a delegate. However, delegates can create a lot of code noise, especially if you have a validation mechanism that you wish to reuse. Consider the following ‘Hello World’ of Waterflow steps;
public MyBot() { dialogs = new DialogSet(); dialogs.Add("greetings", new WaterfallStep[] { async (dc, args, next) => { // Prompt for the guest's name. await dc.Prompt("textPrompt","What is your name?"); }, async(dc, args, next) => { // args; Value: "<name>", Text: "<name>" var userResponse = args["Text"] as string; await dc.Context.SendActivity($"Hi {args["Text"]}!"); await dc.End(); } }); // add the prompt, of type TextPrompt dialogs.Add("textPrompt", new Microsoft.Bot.Builder.Dialogs.TextPrompt(TextValidation)); } private async Task TextValidation(ITurnContext context, TextResult toValidate) { if (toValidate.Text.Length < 4) { toValidate.Status = null; await context.SendActivity("Sorry needs to be > 4"); } }
The problem is that the TextValidation delegate is ugly to re-use. I.e. I want a nicer way to share a simple length validation. This is my solution;
public class ValidatingTextPrompt : Microsoft.Bot.Builder.Dialogs.TextPrompt { public static ValidatingTextPrompt Create(int minimumLength, string minimumLengthMessage) { var obj = new ValidatingTextPrompt(async (context, toValidate) => { if (toValidate.Text.Length < minimumLength) { toValidate.Status = null; await context.SendActivity(minimumLengthMessage); } } ); return obj; } public ValidatingTextPrompt(PromptValidatorEx.PromptValidator<TextResult> validator) : base(validator) { } }
Then you can swap out the TextPrompt with the more specialized code;
dialogs.Add("textPrompt", ValidatingTextPrompt.Create(5, "I can't remember such a short name, please try again"));
If you have thoughts about a better way then please feel free to comment.