【问题标题】:Using FormFlow dialog in Bot Framework在 Bot Framework 中使用 FormFlow 对话框
【发布时间】:2018-08-22 09:27:39
【问题描述】:

我正在使用基于 .Net Core 的 Bot Framework SDK v-4.x。我创建了几个对话框,我可以使用DialogContext.BeginDialogContext.EndDialogContext.Continue 来处理这些对话框。一切正常,但现在我想在对话中间实现一个 FormFlow。我参考了这个链接-https://docs.microsoft.com/en-us/azure/bot-service/dotnet/bot-builder-dotnet-formflow?view=azure-bot-service-3.0

我在 Github (https://github.com/MicrosoftDocs/bot-docs/issues/227) 上发布了这个,根据解决方案,这是我尝试过的-

[Serializable]
public class HelpForm
{
    public string FullName { get; set; }
    public string EmailID { get; set; }
    public string Question { get; set; }
    public DateTime BestTimeToContact { get; set; }
    public List<Priority> Priority { get; set; }
    public static IForm<HelpForm> BuildForm()
    {
        return new FormBuilder<HelpForm>()
            .Message("Please fill out the details as prompted.")
            .Build();
    }
}

public enum Priority
{
    Low,
    Medium,
    High
}

在我的机器人OnTurn 事件中,我正在做这样的事情-

await Microsoft.Bot.Builder.Classic.Dialogs.Conversation.SendAsync(context, () =&gt; FormDialog.FromForm(HelpForm.BuildForm)); //context is of type ITurnContext

这似乎不起作用,我在模拟器中得到响应

抱歉,我的机器人代码有问题。

此外,此链接-https://github.com/Microsoft/botbuilder-dotnet/wiki/Using-Classic-V3-Dialogs-with-V4-SDK 表示 .Net Core 不支持 Microsoft.Bot.Builder.Classic。 请问有什么帮助吗?

更新

根据 Fei 的评论,我得到了异常详细信息。 System.Runtime.Serialization.SerializationException: Type 'System.RuntimeType' in Assembly 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' is not marked as serializable.。虽然我的 HelpForm 类标有Serializable

查看FormFlow 类的元数据,它没有用Serializable 属性标记。

请注意确定错误是否与此有关。

【问题讨论】:

  • Sorry, my bot code is having an issue. 您可以尝试通过CatchExceptionMiddleware来跟踪/检查详细的异常消息。
  • @FeiHan 我收到类似这样的错误-System.Runtime.Serialization.SerializationException: Type 'System.RuntimeType' in Assembly 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' is not marked as serializable.。虽然我的HelpForm 类标有Serializable
  • Microsoft.Bot.Builder.Classic 已被删除。 v4 目前不支持 FormFlow。我一直在这里开发一个端口:github.com/EricDahlvang/Microsoft.Bot.Builder.FormFlow(尚未准备好发布)
  • FormBuilder 在 V4 中存在 github 问题github.com/Microsoft/botbuilder-dotnet/issues/561
  • Bot Builder 社区上周发布了FormFlow version for Bot Builder v4。 Read me

标签: c# asp.net-core botframework


【解决方案1】:

Bot Builder V3 FormFlow 对话框现在可以通过使用最近发布的 Bot.Builder.Community.Dialogs.FormFlow 库在 V4 机器人的上下文中使用。

您的 HelpForm 可以像其他 V4 ComponentDialogs 一样添加到 V4 DialogSet:

_dialogs.Add(FormDialog.FromForm(HelpForm.BuildForm));

这是一个更完整的例子:

访问器:

public class TestEchoBotAccessors
{
    public TestEchoBotAccessors(ConversationState conversationState)
    {
        ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState));
    }

    public ConversationState ConversationState { get; }
    public IStatePropertyAccessor<DialogState> ConversationDialogState { get; set; }
}

Startup.cs 配置服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddBot<TestEchoBotBot>(options =>
    {
        IStorage dataStore = new MemoryStorage();
        options.State.Add(new ConversationState(dataStore));
        options.Middleware.Add(new AutoSaveStateMiddleware(options.State.ToArray()));

        var secretKey = Configuration.GetSection("botFileSecret")?.Value;
        var botFilePath = Configuration.GetSection("botFilePath")?.Value;

        // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
        var botConfig = BotConfiguration.Load(botFilePath ?? @".\TestEchoBot.bot", secretKey);
        services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded. ({botConfig})"));

        // Retrieve current endpoint.
        var environment = _isProduction ? "production" : "development";
        var service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == environment).FirstOrDefault();
        if (!(service is EndpointService endpointService))
        {
            throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
        }

        options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);
    });

    services.AddSingleton(sp =>
    {
        var options = sp.GetRequiredService<IOptions<BotFrameworkOptions>>().Value;
        var conversationState = options.State.OfType<ConversationState>().FirstOrDefault();
        var accessors = new TestEchoBotAccessors(conversationState)
        {
            ConversationDialogState = conversationState.CreateProperty<DialogState>("DialogState")
        };
        return accessors;
    });
}

机器人代码:

public class TestEchoBotBot : IBot
{
    private readonly TestEchoBotAccessors _accessors;
    private DialogSet _dialogs;

    public TestEchoBotBot(TestEchoBotAccessors accessors, ILoggerFactory loggerFactory)
    {
        if (loggerFactory == null)
        {
            throw new System.ArgumentNullException(nameof(loggerFactory));
        }

        _dialogs = new DialogSet(accessors.ConversationDialogState);
        _dialogs.Add(FormDialog.FromForm(HelpForm.BuildForm));
        _accessors = accessors ?? throw new System.ArgumentNullException(nameof(accessors));
    }

    public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        if (turnContext.Activity.Type == ActivityTypes.Message)
        {
            var dialogContext = await _dialogs.CreateContextAsync(turnContext, cancellationToken);
            if (turnContext.Activity.Text?.ToUpper() == "HELP")
            {
                await dialogContext.BeginDialogAsync(typeof(HelpForm).Name, null, cancellationToken);
            }
            else
            {
                var dialogResult = await dialogContext.ContinueDialogAsync(cancellationToken);
                if ((dialogResult.Status == DialogTurnStatus.Cancelled || dialogResult.Status == DialogTurnStatus.Empty))
                {
                    var responseMessage = $"You sent '{turnContext.Activity.Text}'\n";
                    await turnContext.SendActivityAsync(responseMessage);
                }
            }                
        }
    }
}

【讨论】:

    【解决方案2】:

    不幸的是,正如您所发现的,FormFlow 不适用于 v4。

    V4 带有一个非常结构化的瀑布对话框,它可以用来实现类似于 FormFlow 的功能。示例here 展示了如何使用瀑布对话框来询问用户一系列问题,例如姓名、年龄和地址。提示对话框类尤其适合这种类型的任务。包含一个确认提示,您可以在对话框结束时实现该提示以模仿 FormFlow 的确认。

    【讨论】:

      【解决方案3】:
      猜你喜欢
      • 1970-01-01
      • 2019-01-18
      • 2017-03-03
      • 1970-01-01
      • 2017-04-27
      • 2016-10-30
      • 1970-01-01
      • 1970-01-01
      • 2022-11-14
      相关资源
      最近更新 更多