deetwo-id
deetwo-id

Reputation: 255

How to insert records to Azure Table Storage via Microsoft Bot Framework?

at the moment i am working with the Bot Framework 4.0 with C# and i am trying to implement a solution where i store messages from the user in the Azure Table Storage. I already came up with an idea to achive this goal, but my method only works locally when i test it via the Bot Framework Emulator.

When i publish the code to my bot to Azure, the messages wont get stored in the Table Storage. I am a bit confused because i really have no idea why this happens. I already checked the App Insights, but the displayed informations doesnt help me that much.

These are my installed Nugget-Packages:

And also my installed SDKs:

My whole implementation consists of four elements, which I will now shortly explain:

        private static CloudTable GetTableReference()
        {
            var storageAccount = CloudStorageAccount.Parse("<connection-string>");
            var tableClient = storageAccount.CreateCloudTableClient();

            return tableClient.GetTableReference("<table-name>");
        }

The first method is for packing the credentials for the Azure Table Storage. The term is a placeholder and stands for the connection string of the Azure Table Storage. The is a placeholder for the name of the table storage (obviously).

private static void InsertRecord(ITurnContext<IMessageActivity> turnContext, CloudTable table)
        {
            string partitionKey = DateTime.Now.ToString();
            string rowKey = DateTime.Now.ToString();

            var Eintrag = new UserEntity(partitionKey, rowKey)
            {
                UserStatement = $"{turnContext.Activity.Text}",
            };

            var insertOperation = TableOperation.Insert(Eintrag);
            table.ExecuteAsync(insertOperation);
        }

The second method prepares the content for Table Storage. For example, the user's message is also stored here in the "UserStatement" variable, as well as a timestamp.

protected async Task NoMatchFound(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            var table = GetTableReference();
            InsertRecord(turnContext, table);

            // Wird ausgeführt, wenn keine KnowledgeBase gefunden wird
            System.Diagnostics.Debug.WriteLine("### FINDE KEINE PASSENDE ANTWORT ###");
            await turnContext.SendActivityAsync(MessageFactory.Text("Leider kann ich Ihnen hierbei noch nicht weiterhelfen. Ich bin aber schon dabei, Neues zu lernen!"), cancellationToken);
        }

In the last method everything is put together and finally executed. These three mentioned methods are in the same file called "Dispatchbot.cs" (i used the NLP with Dispatch sample for my bot by Microsoft).

using Microsoft.Azure.Cosmos.Table;
using System;

namespace TableStorage
{
    public class UserEntity : TableEntity
    {
        public UserEntity(string partitionKey, string rowKey)
        {
            PartitionKey = partitionKey;
            RowKey = rowKey;
        }

        public UserEntity()
        {
        }

        public string UserStatement { get; set; }

    }
}

The last thing I have is another file called "UserEntity.cs" where the contents for the table entry are packed. The whole implementation is for sure easier to achieve.

The only thing i need to do is to call the NoMatchFound() method and the input from the user should get stored in the Azure Table Storage. But this isnt the case if i try to test this online.

Here is a video where i show that the Table Storage record works without any problems locally: https://youtu.be/fFtzjmOfQDs

I will also attach a screenshot from my app insights - maybe this helps.

I hope you can help me out! If i need to add more informations, feel free to ask for that.

Upvotes: 0

Views: 704

Answers (1)

Ivan Glasenberg
Ivan Glasenberg

Reputation: 30015

I watched the video you provided, and found that in your local machine, the datetime is in this format: 18.01.2021 17:35:59.

So I think the root cause is that when it's deployed to azure, the datetime is in this format: 1/19/2021 10:09:31 AM. And as per this doc Characters Disallowed in Key Fields, the character / is not allowed for the PartitionKey and RowKey properties.

So in the method private static void InsertRecord(xxx), please use the Replace method to replace the character / with character . or other allowed chars. Like below:

    private static void InsertRecord(ITurnContext<IMessageActivity> turnContext, CloudTable table)
    {

        //replace the character / with character .
        string partitionKey = DateTime.Now.ToString().Replace('/','.');
        string rowKey = DateTime.Now.ToString().Replace('/','.');

        var Eintrag = new UserEntity(partitionKey, rowKey)
        {
            UserStatement = $"{turnContext.Activity.Text}",
        };

        var insertOperation = TableOperation.Insert(Eintrag);
        table.ExecuteAsync(insertOperation);
    }

Upvotes: 2

Related Questions