How to store & retrieve Bot Data in Azure Table storage with directLine channel?

前端 未结 3 1766
醉梦人生
醉梦人生 2020-12-18 14:24

I\'m using Microsoft Bot Framework with directLine channel. My Bot is a part of company\'s customer portal from where I fetch some user information

相关标签:
3条回答
  • 2020-12-18 14:36

    The code you are using is using the deprecated default state and will not work. In order to accomplish what you would like it depends on where you are in your code. The deciding factor is if you have access to the context object or not.

    For example if you are in the MessagesController you will not have access to the context object and your code might look like this:

    public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
                {
                    if (activity.Type == ActivityTypes.Message)
                    {
    
                        var message = activity as IMessageActivity;
                        using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                        {
                            var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
                            var key = Address.FromActivity(message);
    
                            var userData = await botDataStore.LoadAsync(key, BotStoreType.BotUserData, CancellationToken.None);
    
                            userData.SetProperty("key 1", "value1");
                            userData.SetProperty("key 2", "value2");
    
                            await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);
                            await botDataStore.FlushAsync(key, CancellationToken.None);
                        }
                        await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
                    }
                } 
    

    then to get the data:

    userData.GetProperty<string>("key 1");
    

    The other situation would be if you did have access to the context object like in a Dialog for example, your code might look like this:

            context.UserData.SetValue("key 1", "value1");
            context.UserData.SetValue("key 2", "value2");
    

    then to get the data:

    context.UserData.GetValue<string>("key 1");
    
    0 讨论(0)
  • 2020-12-18 14:38

    Have you configured your bot to connect to Azure Table Storage in Global.asax.cs, instead of the deprecated default state?
    I have written a blog post with full details on how to move your bot's state to Azure Table Storage which you should review here

    protected void Application_Start()
        {
            Conversation.UpdateContainer(
                builder =>
                {
                    builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
    
                    // Using Azure Table for storage
                    var store = new TableBotDataStore(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);
    
                    builder.Register(c => store)
                        .Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
                        .AsSelf()
                        .SingleInstance();
                });
    
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }
    
    0 讨论(0)
  • 2020-12-18 14:52

    One option is to use the Microsoft Azure Storage Client Library for .NET, as explained in the answer here: How to retrieve Saved Conversation Data in Azure (Tablelogger) Just make sure to follow the exact same PartitionKey strategy as is followed by the TableBotDataStore class, and serialize the data field correctly.

    -- Edit: I tested this out, and it does in fact work as expected.

     public class WebChatController : Controller
    {
        public ActionResult Index()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString;
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
    
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
    
            CloudTable table = tableClient.GetTableReference("BotStore");
            string userId = Guid.NewGuid().ToString();
            TableQuery<BotDataRow> query = new TableQuery<BotDataRow>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, userId));
    
            var dataRow = table.ExecuteQuery(query).FirstOrDefault();
            if(dataRow != null)
            {
                dataRow.Data = Newtonsoft.Json.JsonConvert.SerializeObject(new
                {
                    UserName = "This user's name",
                    Email = "whatever@email.com",
                    GraphAccessToken = "token",
                    TokenExpiryTime = DateTime.Now.AddHours(1)
                });
                dataRow.Timestamp = DateTimeOffset.UtcNow;
                table.Execute(TableOperation.Replace(dataRow));
            }
            else
            {
                var row = new BotDataRow(userId, "userData");
                row.Data = Newtonsoft.Json.JsonConvert.SerializeObject(new
                {
                    UserName = "This user's name",
                    Email = "whatever@email.com",
                    GraphAccessToken = "token",
                    TokenExpiryTime = DateTime.Now.AddHours(1)
                });
                row.Timestamp = DateTimeOffset.UtcNow;
                table.Execute(TableOperation.Insert(row));
            }
    
            var vm = new WebChatModel();
            vm.UserId = userId;
            return View(vm);
        }
    
        public class BotDataRow : TableEntity
        {
            public BotDataRow(string partitionKey, string rowKey)
            {
                this.PartitionKey = partitionKey;
                this.RowKey = rowKey;
            }
    
            public BotDataRow() { }
    
            public bool IsCompressed { get; set; }
            public string Data { get; set; }
        }
    }
    

    In the node bot:

    'use strict';
    
    const builder = require('botbuilder');
    const restify = require('restify');
    var azure = require('botbuilder-azure');
    
    var tableName = 'BotStore';
    var azureTableClient = new azure.AzureTableClient(tableName,'accountname','accountkey');
    var tableStorage = new azure.AzureBotStorage({ gzipData: false }, azureTableClient);
    
    
    const connector = new builder.ChatConnector({
        appId: process.env.MicrosoftAppId,
        appPassword: process.env.MicrosoftAppPassword
        });
    
    const server = restify.createServer();
    server.listen(process.env.port || process.env.PORT || 3979, () => {
        console.log(`${server.name} listening to ${server.url}`);
    });
    
    server.post('/api/messages', connector.listen());
    
    var bot = new builder.UniversalBot(connector)
        .set('storage', tableStorage);;
    
    bot.dialog('/',
    [
        function (session){
            var data = session.userData;
        }
    ]);
    

    0 讨论(0)
提交回复
热议问题