SDK Version: 3.16.1.38846 Code: .Net
Issue Description
We are using Field.SetDefine to define in real time field buttons based on the value gotten from calling a service. To be specific, we have a Source field and a Destination field, the buttons for the Destination and Source field are defined based on the result from the services When a user completes the form, but clicks No on the Confirmation prompt, he gets the following exception:
Failure to complete form. Exception: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Microsoft.Bot.Builder.FormFlow.Advanced.Field`1.ValueDescription(Object value)
at Microsoft.Bot.Builder.FormFlow.Advanced.RecognizeEnumeration`1.<>c__DisplayClass2_0.<.ctor>b__0(Object value)
at Microsoft.Bot.Builder.FormFlow.Advanced.RecognizeEnumeration`1.ValueDescription(Object value)
at Microsoft.Bot.Builder.FormFlow.Advanced.Prompter`1.ValueDescription(IField`1 field, Object value, String format)
at Microsoft.Bot.Builder.FormFlow.Advanced.Prompter`1.ExpandTemplate(String template, String currentChoice, String noValue, T state, IField`1 field, Object[] args, IList`1& buttons)
at Microsoft.Bot.Builder.FormFlow.Advanced.Prompter`1.Prompt(T state, IField`1 field, Object[] args)
at Microsoft.Bot.Builder.FormFlow.Advanced.NavigationField`1..ctor(String name, String startField, IForm`1 form, T state, FormState formState, Fields`1 fields)
at Microsoft.Bot.Builder.FormFlow.Advanced.NavigationStep`1..ctor(String startField, IForm`1 form, T state, FormState formState)
at Microsoft.Bot.Builder.FormFlow.FormDialog`1.<MessageReceived>d__16.MoveNext()
--- End of inner exception stack trace ---
We think this probably happens because the FormFlow code is trying to access the value of the field but the list of buttons changed and now this value no longer exists in the list.
How can I avoid this exception.
Example Code
The complete bot code that reproduces the issue.
public class DynaForm
{
public static ICollection<string> CustomerAccounts { get; set; }
public string Destination { get; set; }
public string source { get; set; }
public static IForm<DynaForm> BuildFormAsync()
{
return new FormBuilder<DynaForm>()
.Message("Welcome to the simple sandwich order bot!")
.Field(new FieldReflector<DynaForm>(nameof(source))
.SetType(null)
.SetDefine((state, field) =>
{
foreach (var item in CustomerAccounts)
{
field
.AddDescription(item,item)
.AddTerms(item, item);
}
return Task.FromResult(true);
})
.SetPrompt(new PromptAttribute("Select the source account \n {||} \n") { ChoiceStyle = ChoiceStyleOptions.Buttons })
.SetAllowsMultiple(false)
)
.Field(new FieldReflector<DynaForm>(nameof(Destination))
.SetType(null)
.SetDependencies(nameof(source))
.SetDefine((state, field) =>
{
foreach (var item in CustomerAccounts)
{
field
.AddDescription(item, item)
.AddTerms(item, item);
}
return Task.FromResult(true);
})
.SetPrompt(new PromptAttribute("Select the destination account \n {||} \n") { ChoiceStyle = ChoiceStyleOptions.Buttons })
.SetAllowsMultiple(false)
)
.Confirm("Do you want to continue? {||}")
.Build();
}
}
Expected Behavior
When user selects No on confirm prompt, the form field should be displayed for the users to select the field to change.
I responded to you via GitHub, as it looks like you have the same question posted twice: https://github.com/Microsoft/BotBuilder/issues/5060