【问题标题】:UserProfile state is null on webchat but ok on directline and emulatorUserProfile 状态在 webchat 上为空,但在直线和模拟器上正常
【发布时间】:2019-02-09 03:31:19
【问题描述】:

我将 StateBotAccessor 传递给我的多对话框机器人。我注意到在 webchat 上,通过 _stateBotAccessor.UserProfileAccessor.GetAsync() 检索 userProfile 返回 null,但 conversationData 是持久的。通过模拟器和直线测试显示正确填充的 userProfile。

I created a git project built from EnterpriseBot template to show the problem.

这是我的简单 UserProfile 类:

public class UserProfile
{
    public UserProfile(string name)
    {
        this.UserName = name;
    }

    public string UserName { get; set; }
}

这是我的简单 ConversationData 类:

public class ConversationData
{
    public ConversationData(string channelId)
    {
        ChannelId = channelId;
    }

    // The ID of the user's channel.
    public string ChannelId { get; set; }
}

这是我的 StateBotAccessor 类:

public class StateBotAccessors
{
    public StateBotAccessors(ConversationState conversationState, UserState userState)
    {
        ConversationState = conversationState ?? throw new ArgumentNullException("UserProfile");
        UserState = userState ?? throw new ArgumentNullException("ConversationData");
    }

    public IStatePropertyAccessor<UserProfile> UserProfileAccessor { get; set; }

    public IStatePropertyAccessor<ConversationData> ConversationDataAccessor { get; set; }

    public IStatePropertyAccessor<DialogState> DialogStateAccessor { get; set; }

    public ConversationState ConversationState { get; }

    public UserState UserState { get; }
}

在 Startup.cs 上我注册了 StateBotAccessors。我这里使用了 inMemory 存储,我也用 blob 存储进行了测试,但结果是一样的。

        var dataStore = new MemoryStorage();
        var userState = new UserState(dataStore);
        var conversationState = new ConversationState(dataStore);

        services.AddSingleton(dataStore);

        var stateBotAccessors = new StateBotAccessors(conversationState, userState)
        {
            DialogStateAccessor = conversationState.CreateProperty<DialogState>("DialogState"),
            ConversationDataAccessor = conversationState.CreateProperty<ConversationData>("ConversationData"),
            UserProfileAccessor = userState.CreateProperty<UserProfile>("UserProfile"),
        };
        services.AddSingleton(stateBotAccessors);

在我的 MainDialog.OnStartAsync() 上,我立即设置了 userProfile 和 conversationData:

    protected override async Task OnStartAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
    {
        var context = dc.Context;

        // set userprofile and conversationdata
        await _accessors.ConversationDataAccessor.SetAsync(context, new ConversationData(dc.Context.Activity.ChannelId));
        await _accessors.UserProfileAccessor.SetAsync(context, new UserProfile("Elena"));

        await dc.Context.SendActivityAsync($"ConversationData and UserProfile were set in MainDialog.OnStartAsync()");

        // easier testing, I have this as a convenience method
        var reply = context.Activity.CreateReply();
        reply.Text = "Say 'print out state' or click the button.";
        reply.SuggestedActions = new SuggestedActions()
        {
            Actions = new List<CardAction>()
                {
                    new CardAction(type: ActionTypes.ImBack, title: "Test State", value: "print out state"),
                }
        };
        await context.SendActivityAsync(reply);
    }

如果用户的文本输入是“打印状态”,我会调用 SecondDialog,然后我会打印出 conversationData 和 userProfile 的内容,但在 webchat 客户端上 userProfile 始终为 NULL:

        var conversationState = await _accessors.ConversationDataAccessor.GetAsync(sc.Context, () => null);
        var userProfile = await _accessors.UserProfileAccessor.GetAsync(sc.Context, () => null);

        await sc.Context.SendActivityAsync($"conversationState.ChannelId: {conversationState?.ChannelId}");
        await sc.Context.SendActivityAsync($"userProfile.UserName: {userProfile?.UserName}");

测试结果如下:

示例网络聊天和直线客户端位于 git 项目的 /Clients 文件夹下。 我的网络聊天客户端很简单:

    const res = await fetch('https://directline.botframework.com/v3/directline/conversations', 
        { 
            method: 'POST',
            headers: {
                "Authorization": "Bearer mySecretKey",            
            },
        });
    const { token } = await res.json();

    var dl = window.WebChat.createDirectLine({ token });
    window.WebChat.renderWebChat({
      directLine: dl,
      user : user,
    }, document.getElementById('webchat'));
    document.querySelector('#webchat > *').focus();

我希望 userProfile 像在模拟器和直线频道上一样保留在网络聊天频道上。有什么我想念的吗?可能对网络聊天频道进行一些特殊处理?

【问题讨论】:

  • @mjwills 我清理了 git 项目,然后为反映问题的示例直连和网络聊天客户端添加了一个新文件夹 /Clients。
  • @mjwills 我再次编辑并将相关代码放入问题文本本身。谢谢你指导我。

标签: c# botframework


【解决方案1】:

Webchat 客户端对 userId 非常特殊 - 除非正确配置了特定的用户 ID,否则会话不会持久化。

...
var user = {id: 'test@test.com',
            name: 'You'
};
....
var dl = window.WebChat.createDirectLine({ token });
window.WebChat.renderWebChat({
      directLine: dl,
      userId : user.id,
    }, document.getElementById('webchat'));
    document.querySelector('#webchat > *').focus();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-23
    • 1970-01-01
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多