已迁移的bot状态提供程序,但仍调用state.botframework.com

时间:2017-12-22 15:44:19

标签: c# botframework

我迁移到Table Azure Provider以管理Microsoft bot框架状态。

在我的遥测中,我看到依赖关系被调用到我的新表Azure存储但是我仍然看到很多调用state.botframework.com,有些调用通常是随机的慢响应时间。

这似乎不正常,因为我希望所有的呼叫都被定向到我的新私人州提供商:

实施例: https://state.botframework.com/v3/botstate/facebook/users/999999999999

调用新的私有州提供者的示例: https://xxxxxxxxxx.table.core.windows.net:443/botdata(PartitionKey=' Facebook的:私人',RowKey =' XXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXX

其他潜在相关信息:

  • 在切换到表azure存储之前,应用程序使用Microsoft State提供程序进行了一段时间的直播
  • 我不会在机器人状态下仅保存与用户对话状态的任何关键任务信息;如果没有重大影响,我可以放松一下。
  • 机器人使用保存在自定义SQL数据库中的恢复cookie发送通知。
  • 这是Table Azure Provider在Autofac模块中注册的方式:
protected override void Load(ContainerBuilder builder)
{
    base.Load(builder);

    //Register custom datastore
    builder
        .RegisterKeyedType<TableBotDataStore, IBotDataStore<BotData>>()
        .Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
        .WithParameter((pi, c) => pi.Name == "connectionString",
                            (pi, c) => 
        ConfigurationManager.ConnectionStrings["X"].ConnectionString)
        .SingleInstance();

    builder.RegisterAdapterChain<IBotDataStore<BotData>>
            (
                typeof(TableBotDataStore),
                typeof(CachingBotDataStore)

            )
            .InstancePerLifetimeScope();
}
  • 我有以下方法检查已保存的状态版本与正在运行的服务版本。引入此代码是因为有时用户会出现序列化对话状态,该状态与使用新版本的对话框中所做的更改不兼容。
public static async Task CheckClientVersion(Activity activity)
{    
    StateClient stateClient = activity.GetStateClient();
    BotData userData = stateClient.BotState.GetUserData(activity.ChannelId, activity.From.Id);
    if (userData?.GetProperty<string>("version")?.CompareTo(Assembly.GetExecutingAssembly().GetName().Version.ToString()) != 0)
    {

        string[] result = await stateClient.BotState.DeleteStateForUserAsync(activity.ChannelId, activity.From.Id, CancellationToken.None);
        userData = stateClient.BotState.GetUserData(activity.ChannelId, activity.From.Id);
        userData.SetProperty<string>("version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
        await stateClient.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, userData);
    }
}

1 个答案:

答案 0 :(得分:3)

您的第二个代码段是Dialog还是MessagesController?问题是您使用activity.GetStateClient 始终调用默认状态客户端而不是您自己的自定义客户端。

如果您在MessagesController

中操纵状态,那么为了完成您想要的代码,必须使用类似于下面的代码
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
            {
                if (activity.Type == ActivityTypes.Message)
                {

                    var message = activity as IMessageActivity;
                    using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                    {
                        var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
                        var key = Address.FromActivity(message);

                        var userData = await botDataStore.LoadAsync(key, BotStoreType.BotUserData, CancellationToken.None);

                        userData.SetProperty("key 1", "value1");
                        userData.SetProperty("key 2", "value2");

                        await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);
                        await botDataStore.FlushAsync(key, CancellationToken.None);
                    }
                    await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
                }
            }   

回答您的跟进问题:

using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
            {
                var token = new CancellationToken();
                var botData = scope.Resolve<IBotData>();
                await botData.LoadAsync(token);

                var stack = scope.Resolve<IDialogStack>();
                stack.Reset();

                botData.UserData.Clear(); 
                botData.ConversationData.Clear();
                botData.PrivateConversationData.Clear();
                await botData.FlushAsync(token);

                var botToUser = scope.Resolve<IBotToUser>();
                await botToUser.PostAsync(message.CreateReply($"{timerMessage}  Conversation aborted."));
            }