Manage state data in the v3 C# SDK
APPLIES TO: SDK v3
The Bot Builder Framework enables your bot to store and retrieve state data that is associated with a user, a conversation, or a specific user within the context of a specific conversation. State data can be used for many purposes, such as determining where the prior conversation left off or simply greeting a returning user by name. If you store a user's preferences, you can use that information to customize the conversation the next time you chat. For example, you might alert the user to a news article about a topic that interests them, or alert a user when an appointment becomes available.
For testing and prototyping purposes, you can use the Bot Builder Framework's in-memory data storage. For production bots, you can implement your own storage adapter or use one of Azure Extensions. The Azure Extensions allow you to store your bot's state data in either Table Storage, CosmosDB, or SQL. This article will show you how to use the in-memory storage adapter to store your bot's state data.
Important
The Bot Framework State Service API is not recommended for production environments, and may be deprecated in a future release. It is recommended that you update your bot code to use the in-memory storage adapter for testing purposes or use one of the Azure Extensions for production bots.
In-memory data storage
In-memory data storage is intended for testing only. This storage is volatile and temporary. The data is cleared each time the bot is restarted. To use the in-memory storage for testing purposes, you will need to:
Install the following NuGet packages:
- Microsoft.Bot.Builder.Azure
- Autofac.WebApi2
In the Application_Start method, create a new instance of the in-memory storage, and register the new data store:
// Global.asax file
var store = new InMemoryDataStore();
Conversation.UpdateContainer(
builder =>
{
builder.Register(c => store)
.Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
.AsSelf()
.SingleInstance();
builder.Register(c => new CachingBotDataStore(store,
CachingBotDataStoreConsistencyPolicy
.ETagBasedConsistency))
.As<IBotDataStore<BotData>>()
.AsSelf()
.InstancePerLifetimeScope();
});
GlobalConfiguration.Configure(WebApiConfig.Register);
You can use this method to set your own custom data storage or use any of the Azure Extensions.
Manage custom data storage
For performance and security reasons in the production environment, you may implement your own data storage or consider implementing one of the following data storage options:
With either of these Azure Extensions options, the mechanism for setting and persisting data via the Bot Framework SDK for .NET remains the same as the in-memory data storage.
Bot state methods
This table lists the methods that you can use to manage state data.
Method | Scoped to | Objective |
---|---|---|
GetUserData |
User | Get state data that has previously been saved for the user on the specified channel |
GetConversationData |
Conversation | Get state data that has previously been saved for the conversation on the specified channel |
GetPrivateConversationData |
User and Conversation | Get state data that has previously been saved for the user within the conversation on the specified channel |
SetUserData |
User | Save state data for the user on the specified channel |
SetConversationData |
Conversation | Save state data for the conversation on the specified channel. Note: Because the DeleteStateForUser method does not delete data that has been stored using the SetConversationData method, you must NOT use this method to store a user's personally identifiable information (PII). |
SetPrivateConversationData |
User and Conversation | Save state data for the user within the conversation on the specified channel |
DeleteStateForUser |
User | Delete state data for the user that has previously been stored by using either the SetUserData method or the SetPrivateConversationData method. Note: Your bot should call this method when it receives an activity of type deleteUserData or an activity of type contactRelationUpdate that indicates the bot has been removed from the user's contact list. |
If your bot saves state data by using one of the "Set...Data" methods, future messages that your bot receives in the same context will contain that data, which your bot can access by using the corresponding "Get...Data" method.
Useful properties for managing state data
Each Activity object contains properties that you will use to manage state data.
Property | Description | Use case |
---|---|---|
From |
Uniquely identifies a user on a channel | Storing and retrieving state data that is associated with a user |
Conversation |
Uniquely identifies a conversation | Storing and retrieving state data that is associated with a conversation |
From and Conversation |
Uniquely identifies a user and conversation | Storing and retrieving state data that is associated with a specific user within the context of a specific conversation |
Note
You may use these property values as keys even if you opt to store state data in your own database, rather than using the Bot Framework state data store.
Handle concurrency issues
Your bot may receive an error response with HTTP status code 412 Precondition Failed when it attempts to save state data, if another instance of the bot has changed the data. You can design your bot to account for this scenario, as shown in the following code example.
var builder = new ContainerBuilder();
builder
.Register(c => new CachingBotDataStore(c.Resolve<ConnectorStore>(), CachingBotDataStoreConsistencyPolicy.LastWriteWins))
.As<IBotDataStore<BotData>>()
.AsSelf()
.InstancePerLifetimeScope();
builder.Update(Conversation.Container);