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.