我正在将 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}");
示例网络聊天和直接客户端位于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渠道上保持不变。有什么我想念的吗?也许对网络聊天频道有一些特殊处理?
答案 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();