Bot Framework的context.Wait()不等待用户输入

时间:2017-11-03 16:44:56

标签: c# .net bots botframework

我开始开发一个简单的Bot,从文档中的Echo bot发展而来。我很快就遇到了问题。

我在RootDialog上有这三种方法:

public async Task StartAsync(IDialogContext context)
{
   await context.PostAsync("Olá! Eu sou um bot!");
   await context.PostAsync("Qual é o teu nome?");

   context.Wait(NameReceivedAsync);
}

private async Task NameReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
   var activity = await result as Activity;

   userName = activity.Text;

   await context.PostAsync($"Olá {userName}. Podes dizer alguma coisa e eu vou repetir.");

   context.Wait(MessageReceivedAsync);
}

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
   var activity = await result as Activity;

   // calculate something for us to return
   int length = (activity.Text ?? string.Empty).Length;

   // return our reply to the user
   await context.PostAsync($"Tu disseste { activity.Text}, que tem {length} caracteres");

   context.Wait(MessageReceivedAsync);
}

我的MessageController Post方法是这样的:

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
   await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());

   return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);
}

想法是让机器人立即发送两条消息,等待来自用户的userName输入,发送另一条消息,然后转到 MessageReceivedAsync ,在那里他将启动他的echo循环。问题是机器人没有等待输入,只是在 MessageReceivedAsync 的末尾停止,在那里他将启动回声。

我似乎无法理解为什么会发生这种情况,因为从我看到的 context.Wait(...)应该让Bot等待输入,这是没有发生的。我正在使用Chrome上的Bot Framework Channel Emulator进行测试,如果这有任何区别的话。

2 个答案:

答案 0 :(得分:1)

context.Wait(方法)有点令人困惑,因为它实际上设置了一个“继续委托来指定收到新消息时应该调用的方法”来自:https://docs.microsoft.com/en-us/bot-framework/dotnet/bot-builder-dotnet-dialogs#implementation-details但是,context.Wait (方法)in .StartAsync将执行&#34;方法&#34;因为对话框是第一次运行所以立即。

如果您将代码更改为以下内容,它应该按预期工作:

[Serializable]
    public class RootDialogTest : IDialog<object>
    {
        public async Task StartAsync(IDialogContext context)
        {
            context.Wait(NameReceivedAsync);
        }

        private async Task NameReceivedAsync(IDialogContext context, IAwaitable<object> result)
        {
            var activity = await result as Activity;

            if (!context.UserData.ContainsKey("askedname"))
            {
                await context.PostAsync("Olá! Eu sou um bot!");
                await context.PostAsync("Qual é o teu nome?");
                context.UserData.SetValue("askedname", true);
                context.Wait(NameReceivedAsync);
            }
            else
            {
                var userName = activity.Text;                
                await context.PostAsync($"Olá {userName}. Podes dizer alguma coisa e eu vou repetir.");
                context.Wait(MessageReceivedAsync);
            }
        }

        private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
        {
            var activity = await result as Activity;

            // calculate something for us to return
            int length = (activity.Text ?? string.Empty).Length;

            // return our reply to the user
            await context.PostAsync($"Tu disseste { activity.Text}, que tem {length} caracteres");

            context.Wait(MessageReceivedAsync);
        }
    }

编辑:另一个选项,对当前对话框的更改较少:

[Serializable]
public class RootDialogTest : IDialog<object>
{
    public async Task StartAsync(IDialogContext context)
    {
        await context.PostAsync("Olá! Eu sou um bot!");
        await context.PostAsync("Qual é o teu nome?");

        context.Wait(SetupMethodWait);
    }
    private async Task SetupMethodWait(IDialogContext context, IAwaitable<object> result)
    {
        context.Wait(NameReceivedAsync);
    }

    private async Task NameReceivedAsync(IDialogContext context, IAwaitable<object> result)
    {
        var activity = await result as Activity;

        var userName = activity.Text;

        await context.PostAsync($"Olá {userName}. Podes dizer alguma coisa e eu vou repetir.");

        context.Wait(MessageReceivedAsync);
    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
    {
        var activity = await result as Activity;

        // calculate something for us to return
        int length = (activity.Text ?? string.Empty).Length;

        // return our reply to the user
        await context.PostAsync($"Tu disseste { activity.Text}, que tem {length} caracteres");

        context.Wait(MessageReceivedAsync);
    }
}

答案 1 :(得分:0)

从我使用Bot框架开发时可以看出,Conversation.SendAsync()就像context.Forward()一样将消息转发到RootDialog()

我建议使用AskNameDialog()使用context.Call()将用户引导到单独的对话框,并在那里处理您的代码。

看看BotBuilder提供的样本 https://github.com/Microsoft/BotBuilder-Samples他们应该帮助你理解。