如何在认证时转发用户消息
How to forward user's message on authentication
我正在使用 Bot Framework 和 AzureAuthDialog 对用户进行身份验证。
机器人首先询问用户他想要什么。每当用户写一条消息时,我们都会检查他是否经过身份验证。如果我们发现他没有认证,我们想请他认证。一旦他完成身份验证,我想继续处理他在身份验证之前的请求。
另一方面,目前发生的情况是,在用户通过身份验证后,我们丢失了用户消息。这是代码,请参阅内联注释以了解更多信息:
public class IntentHandler : LuisDialog<object>
{
protected override async Task MessageReceived(IDialogContext context, IAwaitable<IMessageActivity> item)
{
if (!await context.IsUserAuthenticated(m_resourceId))
{
// this has the user's message
var message = await item;
// The next thing that is called here is ResumeAfterAuth function, but it does not have the user's message anymore
await context.Forward(new AzureAuthDialog(m_resourceId), ResumeAfterAuth, message, CancellationToken.None);
}
else
{
await base.MessageReceived(context, item);
}
}
private async Task ResumeAfterAuth(IDialogContext context, IAwaitable<string> item)
{
// this does not have the users's message, it only includes "User is loged in"
var message = await item;
await context.PostAsync(message);
PrivateTracer.Tracer.TraceInformation($"User {context.GetUserMail()} signed in");
await context.PostAsync(c_welcomeQuestion);
}
}
知道如何在身份验证之前传递用户消息吗?
我知道我可以将用户的消息保存在 MessageReceived enter code here
的一个字段中,但这看起来太丑陋了。还有别的办法吗?
您的 ResumeAfterAuth 方法中的 IAwaitable 是您调用的对话框的结果 (AzureAuthDialog),不是初始用户的消息。
如果您不拥有 AzureAuthDialog,您需要自己保留原始消息并将其传递给回调(ResumeAfterAuth).您可以将其保留为对话框的成员变量 class 或通过 lambda 函数的闭包,如下所示:
if (!await context.IsUserAuthenticated(m_resourceId))
{
var initialUserText = (await item).Text;
await context.Forward(new AzureAuthDialog(m_resourceId), (_context, _item) => ResumeAfterAuth(_context, _item, initialUserText), message, CancellationToken.None);
}
您的回调方法签名如下所示:
private async Task ResumeAfterAuth(IDialogContext context, IAwaitable<string> item, string initialUserText)
如果您拥有 AzureAuthDialog,我想您最好在完成后 return 将原始用户文本发送给您。
编辑:您将需要配置 BotFramework 以允许它序列化闭包,如果您还没有这样做,如 described here。您可以通过将此添加到服务的启动方法来实现:
var builder = new ContainerBuilder();
builder.RegisterModule(new ReflectionSurrogateModule());
builder.Update(Conversation.Container);
@andre 提到的一种方法,另一种最好的方法是将用户消息存储在局部变量中,然后在身份验证将存储的用户消息传递给它之后调用 base.MessageReceived 函数.代码通常是这样的:
class IntentHandler : LuisDialog<object>
{
private string userToBot;
protected override async Task MessageReceived(IDialogContext context, IAwaitable<IMessageActivity> item)
{
var message = await item;
//No way to get the message in the LuisIntent methods so saving it here
userToBot = message.Text.ToLowerInvariant();
if (message.Type != ActivityTypes.Message)
{
await base.MessageReceived(context, item);
return;
}
if (!await context.IsUserAuthenticated(m_resourceId))
{
await context.Forward(new AzureAuthDialog(m_resourceId), ResumeAfterAuth, message, CancellationToken.None);
}
else
{
await base.MessageReceived(context, item);
}
}
private async Task ResumeAfterAuth(IDialogContext context, IAwaitable<string> result)
{
var message = await
await context.PostAsync(message);
Activity activity = (Activity)context.Activity;
//Store the saved message back to the activity
activity.Text = userToBot;
//Reset the saved message
userToBot = string.Empty;
//Call the base.MessageReceived to trigger the LUIS intenet
await base.MessageReceived(context, Awaitable.FromItem(activity));
}
}
我正在使用 Bot Framework 和 AzureAuthDialog 对用户进行身份验证。
机器人首先询问用户他想要什么。每当用户写一条消息时,我们都会检查他是否经过身份验证。如果我们发现他没有认证,我们想请他认证。一旦他完成身份验证,我想继续处理他在身份验证之前的请求。
另一方面,目前发生的情况是,在用户通过身份验证后,我们丢失了用户消息。这是代码,请参阅内联注释以了解更多信息:
public class IntentHandler : LuisDialog<object>
{
protected override async Task MessageReceived(IDialogContext context, IAwaitable<IMessageActivity> item)
{
if (!await context.IsUserAuthenticated(m_resourceId))
{
// this has the user's message
var message = await item;
// The next thing that is called here is ResumeAfterAuth function, but it does not have the user's message anymore
await context.Forward(new AzureAuthDialog(m_resourceId), ResumeAfterAuth, message, CancellationToken.None);
}
else
{
await base.MessageReceived(context, item);
}
}
private async Task ResumeAfterAuth(IDialogContext context, IAwaitable<string> item)
{
// this does not have the users's message, it only includes "User is loged in"
var message = await item;
await context.PostAsync(message);
PrivateTracer.Tracer.TraceInformation($"User {context.GetUserMail()} signed in");
await context.PostAsync(c_welcomeQuestion);
}
}
知道如何在身份验证之前传递用户消息吗?
我知道我可以将用户的消息保存在 MessageReceived enter code here
的一个字段中,但这看起来太丑陋了。还有别的办法吗?
您的 ResumeAfterAuth 方法中的 IAwaitable 是您调用的对话框的结果 (AzureAuthDialog),不是初始用户的消息。
如果您不拥有 AzureAuthDialog,您需要自己保留原始消息并将其传递给回调(ResumeAfterAuth).您可以将其保留为对话框的成员变量 class 或通过 lambda 函数的闭包,如下所示:
if (!await context.IsUserAuthenticated(m_resourceId))
{
var initialUserText = (await item).Text;
await context.Forward(new AzureAuthDialog(m_resourceId), (_context, _item) => ResumeAfterAuth(_context, _item, initialUserText), message, CancellationToken.None);
}
您的回调方法签名如下所示:
private async Task ResumeAfterAuth(IDialogContext context, IAwaitable<string> item, string initialUserText)
如果您拥有 AzureAuthDialog,我想您最好在完成后 return 将原始用户文本发送给您。
编辑:您将需要配置 BotFramework 以允许它序列化闭包,如果您还没有这样做,如 described here。您可以通过将此添加到服务的启动方法来实现:
var builder = new ContainerBuilder();
builder.RegisterModule(new ReflectionSurrogateModule());
builder.Update(Conversation.Container);
@andre 提到的一种方法,另一种最好的方法是将用户消息存储在局部变量中,然后在身份验证将存储的用户消息传递给它之后调用 base.MessageReceived 函数.代码通常是这样的:
class IntentHandler : LuisDialog<object>
{
private string userToBot;
protected override async Task MessageReceived(IDialogContext context, IAwaitable<IMessageActivity> item)
{
var message = await item;
//No way to get the message in the LuisIntent methods so saving it here
userToBot = message.Text.ToLowerInvariant();
if (message.Type != ActivityTypes.Message)
{
await base.MessageReceived(context, item);
return;
}
if (!await context.IsUserAuthenticated(m_resourceId))
{
await context.Forward(new AzureAuthDialog(m_resourceId), ResumeAfterAuth, message, CancellationToken.None);
}
else
{
await base.MessageReceived(context, item);
}
}
private async Task ResumeAfterAuth(IDialogContext context, IAwaitable<string> result)
{
var message = await
await context.PostAsync(message);
Activity activity = (Activity)context.Activity;
//Store the saved message back to the activity
activity.Text = userToBot;
//Reset the saved message
userToBot = string.Empty;
//Call the base.MessageReceived to trigger the LUIS intenet
await base.MessageReceived(context, Awaitable.FromItem(activity));
}
}