在网络聊天中,UserProfile状态为null,但在直线和模拟器上则为

时间:2019-02-09 03:31:19

标签: c# botframework

我正在将 StateBotAccessor 传递给我的多对话框机器人。我注意到在网络聊天上,通过_stateBotAccessor.UserProfileAccessor.GetAsync()检索userProfile会返回null,但是持久化了sessionData。通过仿真器和直接线进行的测试显示正确填充的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和sessionData:

    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,然后我打印出sessionData和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}");

测试结果如下: enter image description here

示例网络聊天和直接客户端位于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像在模拟器和直接渠道上一样,在webchat渠道上保持不变。有什么我想念的吗?也许对网络聊天频道有一些特殊处理?

1 个答案:

答案 0 :(得分:0)

使用 userId 的Webchat客户端非常特别-除非正确配置了特定的用户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();