Create Bot for Microsoft Graph with DevOps 17: BotBuilder features – State Service
In this article, I explain state service.
State Service
Remembering what user said, or even understanding the current context is the important part of intelligent bot. Bot Framework offer a state service to store these state information. Dialog, for example, also using it to track the conversation. See here for more detail.
Scope
There are three scopes for state.
- User (UserData): A user state for each channel. Store the state for a user which are not regarding to specific conversations.
- Conversation (ConversationData): A state relates to the conversation.
- Private Conversation (PrivateConversationData): A user state for the specific conversation.
Where to store the state?
By default, it stores somewhere in the cloud so that developers don’t need to care about. But if you prefer to save them within your reach, you can store them in Azure Table Storage or DocumentDB. See the sample here. By selecting your own storage, it could be faster.
There are several caveats.
- As state is saved per channel, data will be saved separately if same user uses multi-channel.
- Only serializable object can be saved.
- Data can be up to 64kb.
- State won’t be deleted even when you release new bot. If you use emulator, state will be deleted when you close the emulator. This behavior may confuse developers when testing in emulator often.
State Client
There are several ways to create state client.
Create new client
StateClient stateClient = new StateClient(new MicrosoftAppCredentials(microsoftAppId, microsoftAppPassword));
Create from Activity
StateClient stateClient = activity.GetStateClient();
If you use dialog, it comes with IDialogContext.
See more detail here.
StateService in the O365bot
There are several places I (or BotBuilder) utilize the service.
Dialog
Dialog and FormFlow using state service to track the state. If you see PrivateConversationData while debugging, you can see the DialogState.
Office 365 Webhook Subscription
I also store the Office 365 Subscription Id to UserData.
var subscriptionId = context.UserData.GetValueOrDefault<string>("SubscriptionId", "");
if (string.IsNullOrEmpty(subscriptionId))
{
subscriptionId = await service.SubscribeEventChange();
context.UserData.SetValue("SubscriptionId", subscriptionId);
}
AuthBot
AuthBot also using the state service. Check out the GitHub code.
Summery
Imagine how much work you can save by using out-of-box state service. However, it has several limitations to consider, so use it wisely.
Ken