Greg
Greg

Reputation: 105

Migrated bot state provider but calls to state.botframework.com are still being made

I migrated to a Table Azure Provider for managing Microsoft bot framework state.

In my telemetry, I see dependencies call being made to my new Table Azure Storage however I still see a lot of calls being made to state.botframework.com and some have the usual random slow response time.

This does not seem normal as I would have expect all calls to be directed to my new private state provider:

Example: https://state.botframework.com/v3/botstate/facebook/users/999999999999

Example of call to new private state provider: https://xxxxxxxxxx.table.core.windows.net:443/botdata(PartitionKey='facebook:private',RowKey='XXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXX

Other potential relevant information:

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);
    }
}

Upvotes: 5

Views: 355

Answers (1)

D4RKCIDE
D4RKCIDE

Reputation: 3426

Is your second Code Snippet is that from a Dialog or MessagesController? the issue is you are using activity.GetStateClient which Always calls the default state client rather than your own custom one.

In order to Accomplish what you want code similar to below must be used if you are manipulating state in the 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());
                }
            }   

To answer your follow up question:

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."));
            }

Upvotes: 3

Related Questions