BotFramework 消息控制器通过反向通道设置变量
BotFramework Message Controller set variable via Backchannel
我正在尝试通过 Backchannel 接收一个整数 (1-4),然后将其交给第一个对话框。
我的消息控制器如下所示:
private int option = 1;
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
try
{
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity isTypingReply = activity.CreateReply();
isTypingReply.Type = ActivityTypes.Typing;
await connector.Conversations.ReplyToActivityAsync(isTypingReply);
await Conversation.SendAsync(activity, () => new Dialogs.MenuDialog(option));
}
catch (Exception e)
{
//SendEmail(e);
}
}
else
{
await HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
private async Task HandleSystemMessage(Activity message)
{
if (message.Type == ActivityTypes.DeleteUserData)
{
// Implement user deletion here
// If we handle user deletion, return a real message
}
else if (message.Type == ActivityTypes.ConversationUpdate)
{
}
else if (message.Type == ActivityTypes.ContactRelationUpdate)
{
// Handle add/remove from contact lists
// Activity.From + Activity.Action represent what happened
}
else if (message.Type == ActivityTypes.Typing)
{
// Handle knowing tha the user is typing
}
else if (message.Type == ActivityTypes.Ping)
{
}
else if (message.Type == ActivityTypes.Event && message.Name == "option")
{
// var reply = message.CreateReply();
//reply.Text = message.Value.ToString();
// ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
// await connector.Conversations.ReplyToActivityAsync(reply);
if (message.Value.ToString() == "1")
{
option = 1;
}
else if (message.Value.ToString() == "2")
{
option = 2;
}
else if (message.Value.ToString() == "3")
{
option = 3;
}
else if (message.Value.ToString() == "4")
{
option = 4;
}
else
{
option = 1;
}
}
return;
}
Backchannel 方法调用正确,选项值在函数末尾打印时设置。
但是当第一条消息到来时,机器人总是使用默认的“1”值。
之前可以用,现在不行了,我不明白为什么。
private int option = 1;
作用域为 MessageController,每次调用时都会刷新。您可以使用 PrivateConversationData 来保留事件和消息调用之间的 'option':
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
//retrieve the option value before processing the message
string optionValue = string.Empty;
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
var botData = scope.Resolve<IBotData>();
await botData.LoadAsync(CancellationToken.None);
optionValue = botData.PrivateConversationData.GetValue<string>("option");
}
await Conversation.SendAsync(activity, () => new ParameterizedRootDialog(optionValue));
}
else if (activity.Type == ActivityTypes.Event)
{
var eventActivity = activity.AsEventActivity();
if (string.Equals(eventActivity.Name, "option", StringComparison.InvariantCultureIgnoreCase))
{
//save the option into PrivateConversationData
string optionValue = eventActivity.Value.ToString();
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
var botData = scope.Resolve<IBotData>();
await botData.LoadAsync(CancellationToken.None);
botData.PrivateConversationData.SetValue("option", optionValue);
await botData.FlushAsync(CancellationToken.None);
}
}
}
return Request.CreateResponse(HttpStatusCode.OK);
}
另请注意:使用此方法,无需将选项作为参数发送到对话框。您可以使用 IDialogContext.PrivateConversationData 从对话框本身中检索值。像这样:
var optionFromContext = context.PrivateConversationData.GetValue<string>("option");
我正在尝试通过 Backchannel 接收一个整数 (1-4),然后将其交给第一个对话框。
我的消息控制器如下所示:
private int option = 1;
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
try
{
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity isTypingReply = activity.CreateReply();
isTypingReply.Type = ActivityTypes.Typing;
await connector.Conversations.ReplyToActivityAsync(isTypingReply);
await Conversation.SendAsync(activity, () => new Dialogs.MenuDialog(option));
}
catch (Exception e)
{
//SendEmail(e);
}
}
else
{
await HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
private async Task HandleSystemMessage(Activity message)
{
if (message.Type == ActivityTypes.DeleteUserData)
{
// Implement user deletion here
// If we handle user deletion, return a real message
}
else if (message.Type == ActivityTypes.ConversationUpdate)
{
}
else if (message.Type == ActivityTypes.ContactRelationUpdate)
{
// Handle add/remove from contact lists
// Activity.From + Activity.Action represent what happened
}
else if (message.Type == ActivityTypes.Typing)
{
// Handle knowing tha the user is typing
}
else if (message.Type == ActivityTypes.Ping)
{
}
else if (message.Type == ActivityTypes.Event && message.Name == "option")
{
// var reply = message.CreateReply();
//reply.Text = message.Value.ToString();
// ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
// await connector.Conversations.ReplyToActivityAsync(reply);
if (message.Value.ToString() == "1")
{
option = 1;
}
else if (message.Value.ToString() == "2")
{
option = 2;
}
else if (message.Value.ToString() == "3")
{
option = 3;
}
else if (message.Value.ToString() == "4")
{
option = 4;
}
else
{
option = 1;
}
}
return;
}
Backchannel 方法调用正确,选项值在函数末尾打印时设置。 但是当第一条消息到来时,机器人总是使用默认的“1”值。 之前可以用,现在不行了,我不明白为什么。
private int option = 1;
作用域为 MessageController,每次调用时都会刷新。您可以使用 PrivateConversationData 来保留事件和消息调用之间的 'option':
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
//retrieve the option value before processing the message
string optionValue = string.Empty;
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
var botData = scope.Resolve<IBotData>();
await botData.LoadAsync(CancellationToken.None);
optionValue = botData.PrivateConversationData.GetValue<string>("option");
}
await Conversation.SendAsync(activity, () => new ParameterizedRootDialog(optionValue));
}
else if (activity.Type == ActivityTypes.Event)
{
var eventActivity = activity.AsEventActivity();
if (string.Equals(eventActivity.Name, "option", StringComparison.InvariantCultureIgnoreCase))
{
//save the option into PrivateConversationData
string optionValue = eventActivity.Value.ToString();
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
var botData = scope.Resolve<IBotData>();
await botData.LoadAsync(CancellationToken.None);
botData.PrivateConversationData.SetValue("option", optionValue);
await botData.FlushAsync(CancellationToken.None);
}
}
}
return Request.CreateResponse(HttpStatusCode.OK);
}
另请注意:使用此方法,无需将选项作为参数发送到对话框。您可以使用 IDialogContext.PrivateConversationData 从对话框本身中检索值。像这样:
var optionFromContext = context.PrivateConversationData.GetValue<string>("option");