Microsoft Bot Framework FAQ - IDialogStack.Call VS IDialogStack.Forward (要不要等使用者輸入呢?)

使用 Microsoft Bot Framework 來開發 BOT 時,

我們常常會從 Root Dialog Call 它的 Child Dialg。

您是使用 Call 還是 Forward 呢? 

您知道它們的差別嗎?

有時候我們需要一進到 Child Dialog 就馬上執行先前使用者輸入的東東,而不需等待使用者再輸入一次,

這時,我們要用 Forward 還是 Call 呢? 

我們用以下的程式來測試,

[Serializable]
public class RootDialog : IDialog<object>
{
	public Task StartAsync(IDialogContext context)
        {
            context.PostAsync("這裡是 RootDialog 的 StartAsync");
            context.Wait(MessageReceivedAsync);
            return Task.CompletedTask;
        }

        private async Task AfterChildDialog(IDialogContext context, IAwaitable<object> result)
        {
            var msg = await result;
            await context.PostAsync($"從 Child Dialog 回來! result:{msg}");
            context.Wait(MessageReceivedAsync);
        }

        private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
        {
            var activity = await result as Activity;
            var messageText = activity?.Text;
            await context.PostAsync($"這裡是 RootDialog 的 MessageReceivedAsync, Text:{messageText}");
            var childDialog = new ChildDialog();
			// *** 請調整這裡來測試 *** 
			// await context.Forward(childDialog, AfterChildDialog, activity, CancellationToken.None);
			// or 
            //context.Call(childDialog, AfterChildDialog);
		}
}

[Serializable]
public class ChildDialog : IDialog<string>
{
	public async Task StartAsync(IDialogContext context)
	{
		await context.PostAsync($"這裡是 ChildDialog 的 StartAsync{Environment.NewLine}");
		context.Wait(MessageReceivedAsync);
	}

	public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
	{
		var activity = await result;
		var msg = activity.Text;
		await context.PostAsync($"這裡是 ChildDialog 的 MessageReceivedAsync, Text:{msg}{Environment.NewLine}");
		context.Done($"{msg}");
	}
}

 

當從 MessagesController 將訊息送給 RootDialog , RootDialog 如果使用 await context.Forward 的話,

我們可以發現,它的訊息會直接再轉給 ChildDialog ,而在 ChildDialog 中,並不會等使用者輸入,

在 ChildDialog 的 MessageReceivedAsync Method 中會直接收到剛才使用者的輸入,最後再將收到的文字,

傳回去給 RootDialog,如下,

 

而如果我們在 RootDialog 使用的是 context.Call ,在 ChildDialog 的 MessageReceivedAsync Method 就會等使用者的輸入,

最後再將收到的文字透過 context.Done 傳回 RootDialog,如下,

 

IDialogStack.Call : Call a child dialog and add it to the top of the stack。
IDialogStack.Forward : Call a child dialog, add it to the top of the stack and post the item to the child dialog.

所以就差在有沒有將資料傳送給 Child Dialog 哦 。

所以在前言詢問大家的問題,

如果一進到 Child Dialog 就要立馬執行先前 使用者(或是 Parent Dialog 傳進來)的資料,

我們就需要使用 Forward,如果是要再詢問問題請使用者輸入的話,就使用 Call 。

希望對大家在使用 botframework 上有幫助。

 

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^