Fix infinite loop when asking the user to enter a data

Viewed 61

I need help, I am creating a bot that allows entering a date, I need to validate that the user has entered the corresponding date, otherwise it will come back and ask him to enter the date.

When I do this, it throws me an infinite loop when executing the bot in the emulator

  public PruebaOpciones()
    {
        var waterfallStep = new WaterfallStep[]
       {
           SetPeriodo,
           Confirmation,
           FinalProcess
       };
        AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallStep));
        AddDialog(new TextPrompt(nameof(TextPrompt)));
    }

    private async Task<DialogTurnResult> SetPeriodo(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
      
        while (true)
        {
            string periodo = "Ingresa el mes que quieres consultar por favor.";
            await stepContext.PromptAsync(
                           nameof(TextPrompt),
                           new PromptOptions
                           {
                               Prompt = MessageFactory.Text(periodo),
                           },
                           cancellationToken
                           );
            periodo = periodo.ToLower();
        int periodoLength = periodo.Length;
        if (periodoLength == 1)
        {
                periodo = "0" + periodo;
                break;  
        }
        string[] periodoList = { "enero", "febrero", "marzo", "abril","mayo","junio","julio","agosto","septiembre","octubre",
        "noviembre","diciembre","01", "02", "03", "04", "05","06","07","08","09","10","11","12"};
        List<string> periodoRange = new List<string>(periodoList);
            
            if (periodoRange.Contains(periodo))
            {

                break;
            }
            else
            {
                return await SetPeriodo(stepContext, cancellationToken);
            }
           
        }

        return await stepContext.ContinueDialogAsync(cancellationToken: cancellationToken);
    }

enter image description here

[1]: https://i.stack.imgur.com/CIb4s.png

How can I solve this issue and not throw me an infinite loop and only ask me once and if I enter wrong, come back and ask me?

1 Answers

I don't know anything about the bot framework, but does the call to stepContext.PromptAsync actually end up changing the value of periodo? I don't think so. I think instead you need to examine the return value of the call (see: DialogContext.PromptAsync)

I believe what's happening is that you're setting periodo to the prompt string, showing a dialog to get input from the user, then comparing the prompt string to valid months. This, of course, fails, and you end up in an endless loop.

Also, here are a few other general observations:

  1. You don't need to recreate the list of months on ever iteration. Create it outside the loop once instead. Same with the prompt text.
  2. You don't need to create an array to create a list - just create the list directly.
  3. It looks like you break out of the while loop from the if statement when adding a 0 to periodo. That seems like a logic error.
  4. There's no point in capturing the length property of periodo in a separate variable.
  5. At the end of the loop body, all code paths return something (return will end the loop), so it never actually loops. In the case of bad input, it makes a recursive call to the same method. Instead of calling the method again we can remove the else and just let the loop re-run.

Below is some code that addresses the comments above and might resolve your issue. Someone who actually knows the bot framework, and how to retrieve the user input, will hopefully correct this or give you a better answer.


private async Task<DialogTurnResult> SetPeriodo(WaterfallStepContext stepContext, 
    CancellationToken cancellationToken)
{
    string prompt = "Ingresa el mes que quieres consultar por favor.";

    List<string> periodoRange = new List<string> {
        "enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto",
        "septiembre", "octubre", "noviembre", "diciembre", "01", "02", "03", "04",
        "05", "06", "07", "08", "09", "10", "11", "12" };

    while (true)
    {
        await stepContext.PromptAsync(
            nameof(TextPrompt),
            new PromptOptions { Prompt = MessageFactory.Text(prompt) },
            cancellationToken);

        // Capture the value entered by the user - I'm not exactly sure
        // how to get this, but from the documentation it sounds like 
        // it would look something like this:
        string periodo = ((string)stepContext.Values["periodo"]).ToLower();

        if (periodo.Length == 1)
        {
            periodo = "0" + periodo; 
        }
        
        if (periodoRange.Contains(periodo))
        {
            return await stepContext.ContinueDialogAsync(
                cancellationToken: cancellationToken);
        }       
    }
}
Related