I implemented a bot with the Microsoft BotFramework. For gathering user data, I use ChoicePrompts. When a user doesn't choose one of the proposed options, the ChoicePrompt repeats until the user enters a valid option (this is default behavior from the prompt method).
Unfortunately, after not choosing one of the valid choice options, the user state is refreshed. This means that I lose all the collected user data until that point.
Is this behavior intended or is there a way to prevent this?
You have a couple issues with your code on the link you provided. As I can't see your complete code, I've made a guess at some parts.
const DIALOG_STATE_PROPERTY = 'dialogState';
const USER_PROFILE_PROPERTY = 'user';
const EDUCATION_PROMPT = 'education_prompt';
const MAJOR_PROMPT = 'major_prompt';
constructor(conversationState, userState) {
this.conversationState = conversationState;
this.userState = userState;
this.dialogState = this.conversationState.createProperty(DIALOG_STATE_PROPERTY);
this.userData = this.userState.createProperty(USER_PROFILE_PROPERTY);
this.dialogs = new DialogSet(this.dialogState);
// Add prompts that will be used by the main dialogs.
this.dialogs
.add(new TextPrompt(NAME_PROMPT))
.add(new TextPrompt(AGE_PROMPT))
.add(new TextPrompt(GENDER_PROMPT))
.add(new ChoicePrompt(EDUCATION_PROMPT))
.add(new ChoicePrompt(MAJOR_PROMPT));
// Create dialog for prompting user for profile data
this.dialogs.add(new WaterfallDialog(START_DIALOG, [
this.promptForName.bind(this),
this.promptForAge.bind(this),
this.promptForGender.bind(this),
this.promptForEducation.bind(this),
this.promptForMajor.bind(this),
this.returnUser.bind(this)
]));
this.majors = ['English', 'History', 'Computer Science'];
}
Remember that TextPrompt returns the value in step.result. ChoicePrompt returns the value as step.result.value
I'm assuming that in your "promptForEducation" step where you assign the gender value to user that that value is coming from a choice prompt. If not, you will lose the value. Double check you are specifying the correct source.
.add(new TextPrompt(GENDER_PROMPT))
.add(new ChoicePrompt(EDUCATION_PROMPT))
...
if (!user.gender) {
user.gender = step.result;
// Give user object back to UserState storage
await this.userData.set(step.context, user);
console.log(user);
}
this.majors = ['English', 'History', 'Computer Science'];
...
if (!user.major) {
// Copy List of majors and add "Other" entry
let majorsOther = this.majors.slice(0, this.majors.length);
majorsOther.push('Einen anderen Studiengang');
// return await step.prompt(MAJOR_PROMPT, this.userData.major, majorsOther);
return await step.prompt(MAJOR_PROMPT, 'List of majors:', majorsOther);
}
// Save changes to the user state.
await this.userState.saveChanges(turnContext);
// End this turn by saving changes to the conversation state.
await this.conversationState.saveChanges(turnContext);
If you implement the above, you should be set. I was able to run with no issues and no loss of state. Additionally, repeatedly not answering the ChoicePrompt before finally providing a proper response did not break state.
Hope of help!