【发布时间】: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