Reputation: 3406
I'm trying to build a Simple iForm Based bot. When one Form is completed I want to show another.
Both Forms consist of a single enum value. The first form show correctly. When I select a option, the SelectNextAction
is called as expected.
The first dialog is constructed via:
public static IForm<RootForm> BuildRootForm()
{
IForm<RootForm> ret = new FormBuilder<RootForm>()
.Message("Hi")
.AddRemainingFields()
.OnCompletion(SelectNextAction)
.Build();
return ret;
}
private static async Task SelectNextAction(IDialogContext context, RootForm state)
{
// Tell the user that the form is complete
switch (state.Choice)
{
case MainChoice.Transfer:
IFormDialog<TransferForm> form = FormDialog.FromForm(TransferForm.BuildTransferForm);
context.Call(form, TransferDialogComplete);
break;
default:
break;
}
}
After this code has run TransferDialogComplete
is called:
private async static Task TransferDialogComplete(IDialogContext context, IAwaitable<TransferForm> result)
{
await result;
}
And then a Exception is thrown:
Exception: invalid type: expected EBBot.Dialogs.TransferForm, have RootForm [File of type 'text/plain']
What am I doing wrong? any idea or suggestions?
Upvotes: 0
Views: 298
Reputation: 14787
As I mentioned in the comments, the issue is due to the call of the second form in the OnCompletion
call.
In order to solve this, you should call the second form in the ResumeAfter<T
> method that you specified when you call your first form.
var rootForm = FormDialog.FromForm(RootForm.BuildRootForm);
context.Call(rootForm, AfterRootFormCompleted);
private async Task AfterRootFormCompleted(IDialogContext context, IAwaitable<RootForm> result)
{
try
{
var state = await result;
IFormDialog<TransferForm> form = FormDialog.FromForm(TransferForm.BuildTransferForm);
context.Call(form, TransferDialogComplete);
}
catch (FormCancelledException)
{
// do something;
}
}
Upvotes: 1
Reputation: 2213
The delegate passed into the OnCompletion
method can not be used to call another forms or any other dialogs.
This should only be used for side effects such as calling your service wit the form state results. In any case the completed form state will be passed to the parent dialog.
Source: line 225
For an example look here.
How you can implement this is through the ResumeAfter
method. Here is an example:
[Serializable]
public class RootDialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
var form = new FormDialog<SimpleForm>(new SimpleForm1(),
SimpleForm1.BuildForm);
context.Call(form, ResumeAfterForm1);
}
private async Task ResumeAfterForm1(IDialogContext context, IAwaitable<object> result)
{
var form = new FormDialog<SimpleForm2>(new SimpleForm2(),
SimpleForm2.BuildForm, FormOptions.PromptInStart);
context.Call(form, ResumeAfterForm2);
}
// other code
}
Note: I used the PromptInStart
Because I have noticed that if you don't include this the form will not start right away.
Upvotes: 1