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:

  1. Manage state data with Cosmos DB

  2. Manage state data with Table storage

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

Additional resources