Cosmos,在MessageController中检索对话数据

问题描述 投票:3回答:2

我正在尝试用Azure提供的Cosmos存储替换InMemory存储。

我在会话数据中存储了一些信息,在我的对话框中使用它,如果发送了某个命令,则从我的消息控制器重置它。

我在对话框中访问对话数据的方式是:

context.ConversationData.GetValueOrDefault<String>("varName", "");

我在messageContoller中重置数据的方式是:

StateClient stateClient = activity.GetStateClient();
BotData userData = await stateClient.BotState.GetConversationDataAsync(activity.ChannelId, activity.Conversation.Id);
userData.RemoveProperty("varName");
await stateClient.BotState.SetConversationDataAsync(activity.ChannelId, 
activity.Conversation.Id, userData);

如果我使用InMemory,前一行代码正常工作。一切换到cosmos,代码的重置部分就会失败。在调试问题时,我发现返回的对话数据对象与从对话框中返回的对象数据对象永远不一样,我无法重置变量。

这是我连接到cosmos数据库的方式:

var uri = new Uri(ConfigurationManager.AppSettings["DocumentDbUrl"]);
var key = ConfigurationManager.AppSettings["DocumentDbKey"];
var store = new DocumentDbBotDataStore(uri, key);

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

});

知道为什么会这样吗?

编辑:

当使用im内存存储时,这段代码工作正常,但用cosmos存储替换存储无法在对话框外检索对话数据(对话框正确获取/设置对话数据但StateClents无法正确检索数据,它返回一个空对象,但奇怪的部分是与对话框返回的对象ID具有相同的对话ID)

c# botframework azure-cosmosdb
2个回答
4
投票

在调试问题时,我发现返回的对话数据对象与从对话框中返回的对象数据对象永远不一样,我无法重置变量。

在保存数据和重置数据操作时,请确保使用相同的对话。

此外,我使用以下示例代码进行测试,我可以按预期保存和重置会话数据。

在消息控制器中:

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
    if (activity.Type == ActivityTypes.Message)
    {
        if (activity.Text=="reset")
        {
            var message = activity as IMessageActivity;

            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
            {
                var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
                var key = new AddressKey()
                {
                    BotId = message.Recipient.Id,
                    ChannelId = message.ChannelId,
                    UserId = message.From.Id,
                    ConversationId = message.Conversation.Id,
                    ServiceUrl = message.ServiceUrl
                };
                var userData = await botDataStore.LoadAsync(key, BotStoreType.BotConversationData, CancellationToken.None);

                //var varName = userData.GetProperty<string>("varName");

                userData.SetProperty<object>("varName", null);

                await botDataStore.SaveAsync(key, BotStoreType.BotConversationData, userData, CancellationToken.None);
                await botDataStore.FlushAsync(key, CancellationToken.None);
            }
        }

        await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
    }
    else
    {
        HandleSystemMessage(activity);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK);
    return response;
}

public class AddressKey : IAddress
{
    public string BotId { get; set; }
    public string ChannelId { get; set; }
    public string ConversationId { get; set; }
    public string ServiceUrl { get; set; }
    public string UserId { get; set; }
}

在对话框中:

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
    var activity = await result as Activity;

    // calculate something for us to return
    int length = (activity.Text ?? string.Empty).Length;

    var varName = "";

    if (activity.Text.ToLower().Contains("hello"))
    {
        context.ConversationData.SetValue<string>("varName", activity.Text);
    }

    if (activity.Text.ToLower().Contains("getval"))
    {
        varName = context.ConversationData.GetValueOrDefault<string>("varName", "");

        activity.Text = $"{varName} form cosmos";
    }

    if (activity.Text.ToLower().Contains("remove"))
    {
        activity.Text = "varName is removed";
    }

    // return our reply to the user
    await context.PostAsync($"{activity.Text}");

    context.Wait(MessageReceivedAsync);
}

测试步骤:

enter image description here

输入qazxsw poi后,可以将其保存为Cosmos Db中的会话数据。

hello bot

输入“reset”后,可以发现enter image description here的值被重置为varName

null


1
投票

不推荐使用activity.GetStateClient():enter image description here

它仅使用默认状态服务。如果您使用BotBuilder-Azure进行状态,则不会使用.GetStateClient()检索您的CosmosDb实现。有关如何使用DialogModule.BeginLifetimeScope或dialog.Context方法操作状态,请参阅@Fei的答案。

© www.soinside.com 2019 - 2024. All rights reserved.