Creating a reusable TextPrompt in Bot Framework V4

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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s