GeekzSG
GeekzSG

Reputation: 973

BotFramework PrivateConversationData set issue

We are trying to save a simple serializable object in PrivateConversationData in a Dialog and access it from state in MessagesController

For some reason, after we do Context.Done in the dialog, we are not getting back data stored in the state

    public static async Task SetUserAsync<T>(IActivity activity, T botUser) where T : IBotUser
    {
        if (botUser != null)
        {
            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity.AsMessageActivity()))
            {
                var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
                var key = new AddressKey()
                {
                    BotId = activity.Recipient.Id,
                    ChannelId = activity.ChannelId,
                    UserId = activity.From.Id,
                    ConversationId = activity.Conversation.Id,
                    ServiceUrl = activity.ServiceUrl
                };

                var privateData = await botDataStore.LoadAsync(key, BotStoreType.BotPrivateConversationData, CancellationToken.None);
                privateData.SetProperty<T>(Keys.CacheBotUserKey, botUser);

                await botDataStore.SaveAsync(key, BotStoreType.BotPrivateConversationData, privateData, CancellationToken.None);
                await botDataStore.FlushAsync(key, CancellationToken.None);

            }
        }
    }

The dialog code is as simple as

    public override async Task ProcessMessageAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
    {
        BotUser user = new BotUser { UserId = "user1" };
        await StateHelper.SetUserAsync(context.Activity, user);

        var userFromState = await StateHelper.GetUserAsync<BotUser>(context.Activity);
        Debug.WriteLine("Within dialog (after set) >" + userFromState?.UserId);

        context.Done<object>(null);
    }

and in MessagesController.cs we are simply calling the

      await Conversation.SendAsync(activity, () => new DummyDialog()).ConfigureAwait(false);

      var user = await StateHelper.GetUserAsync<BotUser>(activity);
      System.Diagnostics.Debug.WriteLine("Within MC (end) >" + user?.UserId);

In this case, we get below output

Within dialog (after set) > user1 
Within MC (end) >

Is there anything wrong?

Upvotes: 1

Views: 86

Answers (1)

Eric Dahlvang
Eric Dahlvang

Reputation: 8292

When a dialog loads, the state is loaded with it and can be accessed/saved by using the methods on the Context object. When the dialog completes, the state is persisted by the SDK. If you create a new scope, nested within a dialog, and attempt to load/persist the state: then the dialog state will overwrite it. To work around this, you can add a method your StateHelper that accepts an IDialogContext, and use that while within a Dialog.

Upvotes: 1

Related Questions