c# - 如何将对话从 formflow 转发到 QnaDialog

标签 c# bots botframework formflow

大家好,我是机器人开发的新手,我想弄清楚如何在 formflow 之后将对话转发到 QnaDialog。我的表单流在用户被识别后简单地询问他/她的名字,之后它会简单地说 hi (username) 我想要的是因为用户已经被识别,所以之后的任何消息都会被转发到 QnaDialog。我曾尝试添加一个检查器来标记问候语已经完成,但是由于您只允许一个 Conversation.SendAsync,我现在不知道如何正确纠正这个问题。

表单流

  public class ProfileForm
{
    // these are the fields that will hold the data
    // we will gather with the form
    [Prompt("What is your name? {||}")]
    public string Name;

    // This method 'builds' the form 
    // This method will be called by code we will place
    // in the MakeRootDialog method of the MessagesControlller.cs file
    public static IForm<ProfileForm> BuildForm()
    {
        return new FormBuilder<ProfileForm>()
                .Message("Welcome to the profile bot!")
                .OnCompletion(async (context, profileForm) =>
                {
                    // Set BotUserData
                    context.PrivateConversationData.SetValue<bool>("ProfileComplete", true);
                    context.PrivateConversationData.SetValue<string>("Name", profileForm.Name);
                    // Tell the user that the form is complete
                    await context.PostAsync("Your profile is complete.");
                })
                .Build();
    }


}

消息 Controller

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
    {
        if (activity.Type == ActivityTypes.Message)
        {
            //ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
            //await Conversation.SendAsync(activity, () => new QnADialog());

            #region Formflow

            // Get any saved values
            StateClient sc = activity.GetStateClient();
            BotData userData = sc.BotState.GetPrivateConversationData(
                activity.ChannelId, activity.Conversation.Id, activity.From.Id);
            var boolProfileComplete = userData.GetProperty<bool>("ProfileComplete");
            if (!boolProfileComplete)
            {
                // Call our FormFlow by calling MakeRootDialog
                await Conversation.SendAsync(activity, MakeRootDialog);
            }
            else
            {
                //Check if Personalized Greeting is done
                if (userData.GetProperty<bool>("Greet"))
                {
                    //this doesnt work since their should be only one Conversation.SendAsync.

                    //ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
                    //await Conversation.SendAsync(activity, () => new QnADialog());
                }
                else
                {
                    // Get the saved profile values
                    var Name = userData.GetProperty<string>("Name");
                    userData.SetProperty<bool>("Greet", true);
                    sc.BotState.SetPrivateConversationData(activity.ChannelId, activity.Conversation.Id,activity.From.Id, userData);
                    ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
                    Activity replyMessage = activity.CreateReply(string.Format("Hi {0}!", Name));
                    await connector.Conversations.ReplyToActivityAsync(replyMessage);
                }
            }
            #endregion
        }
        else
        {
            HandleSystemMessage(activity);
        }
        var response = Request.CreateResponse(HttpStatusCode.OK);
        return response;
    }

最佳答案

这是一个使用您的示例的示例。我做了一些小改动,但没有什么是你无法发现的。一点解释:

Controller:我把它清理干净了。它实际上应该只调用根对话框。这样就干净多了。

RootDialog:会先调用窗体。如果表单成功,它将继续到 QnA 对话框。

ProfileForm:只删除了 FormCompleted bool 值。没有必要。

QnADialog:将启动对话框并提出问题,使用填写的名称。我保留默认代码以获得一些反馈。

希望对你有帮助

Controller

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
    if (activity.Type == ActivityTypes.Message)
    {
        await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
    }
    else
    {
        HandleSystemMessage(activity);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK);
    return response;
}

根对话框

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

    private async Task ResumeAfterForm(IDialogContext context, IAwaitable<ProfileForm> result)
    {
        if (context.PrivateConversationData.TryGetValue("Name", out string name))
        {
            context.Call(new QnADialog(), MessageReceivedAsync);
        }
        else
        {
            await context.PostAsync("Something went wrong.");
            context.Wait(MessageReceivedAsync);
        }
    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
    {
        var form = new FormDialog<ProfileForm>(new ProfileForm(), ProfileForm.BuildForm, FormOptions.PromptInStart);
        context.Call(form, ResumeAfterForm);
    }
}

个人资料表格

[Serializable]
public class ProfileForm
{
    // these are the fields that will hold the data
    // we will gather with the form
    [Prompt("What is your name? {||}")]
    public string Name;

    // This method 'builds' the form 
    // This method will be called by code we will place
    // in the MakeRootDialog method of the MessagesControlller.cs file
    public static IForm<ProfileForm> BuildForm()
    {
        return new FormBuilder<ProfileForm>()
                .Message("Welcome to the profile bot!")
                .OnCompletion(async (context, profileForm) =>
                {
                    // Set BotUserData
                    //context.PrivateConversationData.SetValue<bool>("ProfileComplete", true);
                    context.PrivateConversationData.SetValue<string>("Name", profileForm.Name);
                    // Tell the user that the form is complete
                    await context.PostAsync("Your profile is complete.");
                })
                .Build();
    }
}

QnADialog

[Serializable]
public class QnADialog : IDialog<object>
{
    public async Task StartAsync(IDialogContext context)
    {
        context.PrivateConversationData.TryGetValue("Name", out string name);
        await context.PostAsync($"Hello {name}. The QnA Dialog was started. Ask a question.");
        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($"You sent {activity.Text} which was {length} characters");

        context.Wait(MessageReceivedAsync);
    }
}

关于c# - 如何将对话从 formflow 转发到 QnaDialog,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43652451/

相关文章:

c# - 表达式体成员与 Lambda 表达式

c# - 使用 Autofac 返回不同范围内的不同组件

c - 尝试制作 irc 机器人

c# - 无法覆盖 Azure Web App 中的服务器证书验证

c# - LINQ 连接查询返回匹配的记录

node.js - 在 Node.js 中使用 skype-sdk 构建的 Skype bot 无法正常运行?

php - 如何阻止机器人增加 PHP 中的文件下载计数器?

c# - 是否可以将用户过去的对话历史插入/注入(inject)到聊天窗口对话框中?

c# - Bot 框架在部署时缺少 project.json

c# - Luis 意图处理程序向机器人框架抛出异常