Reputation: 973
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
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