C#Microsoft bot框架:如何集成登录对话框并等待登录结果

时间:2019-08-05 09:40:16

标签: c# authentication async-await botframework

我正在尝试在我的团队机器人中添加登录选项。我从git-hub example中获取了示例代码,并将其包含在代码中。

我只希望用户在特殊情况下登录,例如当他想预订房间时。

问题出在登录完成之前,机器人已进入下一步并失败。

                        case LUISIntent.FindRoom:

                            token = await _authToken.GetAsync(turnContext, () => token);
                            if (token.IsNullOrWhiteSpace())
                            {
                                var resultToken = dc.BeginDialogAsync(nameof(SignInDialog),
                                    cancellationToken: cancellationToken);
                                if (resultToken.Status != TaskStatus.WaitingForActivation)
                                {
                                    var tokenResponse = resultToken.Result;
                                    var tokenResult = (TokenResponse)tokenResponse.Result;
                                    token = tokenResult.Token;
                                    await _authToken.SetAsync(turnContext, token, cancellationToken);
                                }

                            }

                            await dc.BeginDialogAsync(nameof(FindRoom), luisResults);

问题是,如何才能以更好的方式集成登录,以及如何停止执行,直到获得登录对话框的返回响应

1 个答案:

答案 0 :(得分:1)

如果您希望机器人在返回令牌之前实质上“暂停”,我将按照示例机器人所显示的进行操作。它有一个瀑布对话框,该对话框一直循环直到显示成功的令牌响应为止。

AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
           {
               PromptStepAsync,
               LoginStepAsync,
               DisplayTokenPhase1Async,
               DisplayTokenPhase2Async,
           }));

           // The initial child Dialog to run.
           InitialDialogId = nameof(WaterfallDialog);
       }

       private async Task<DialogTurnResult> PromptStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
       {
           return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken);
       }

private async Task<DialogTurnResult> LoginStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
       {
           // Get the token from the previous step. Note that we could also have gotten the
           // token directly from the prompt itself. There is an example of this in the next method.
           var tokenResponse = (TokenResponse)stepContext.Result;
           if (tokenResponse != null)
           {
               await stepContext.Context.SendActivityAsync(MessageFactory.Text("You are now logged in."), cancellationToken);
               return await stepContext.PromptAsync(nameof(ConfirmPrompt), new PromptOptions { Prompt = MessageFactory.Text("Would you like to view your token?") }, cancellationToken);
           }

           await stepContext.Context.SendActivityAsync(MessageFactory.Text("Login was not successful please try again."), cancellationToken);
           return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
       }

从这两个步骤可以看到,它会提示,然后进行检查。如果检查失败,则会结束对话框,这意味着当再次向漫游器发送消息时,瀑布将重新开始。这一直持续到返回令牌为止,然后转到“您想查看令牌”提示。显然,您不会问客户他们是否想看他们的代币,但是这个想法很可靠。

case LUISIntent.FindRoom:

//TINY WATERFALL HERE
//this waterfall would be added to your dialogs wherever you add them. 
//for the sake of brevity, i'm skipping that part


//WATERFALL STEP 1:
private async Task<DialogTurnResults> GETTINGYOURLOGIN(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    token = await _authToken.GetAsync(turnContext, () => token);
    return await stepContext.NextAsync(cancellationToken);
}
//WATERFALL STEP 2:

private async Task<DialogTurnResults> CHECKINGYOURLOGIN(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{

// Get the token from the previous step.
//this does a quick check to see if it's NOT null, then goes to the next step.
//OTHERWISE, it continues with your login prompt.
//this way, if your user has ALREADY logged in, and for whatever reason goes BACK to the //book room dialog, they don't have to re-login if it's been a short enough time

if (!token.IsNullOrWhiteSpace())
{
   await dc.BeginDialogAsync(nameof(FindRoom), luisResults);
}

var resultToken = dc.BeginDialogAsync(nameof(SignInDialog),
            cancellationToken: cancellationToken);

if (resultToken.Status != TaskStatus.WaitingForActivation)
{
    var tokenResponse = resultToken.Result;
    var tokenResult = (TokenResponse)tokenResponse.Result;
    token = tokenResult.Token;
    await _authToken.SetAsync(turnContext, token, cancellationToken);
}
// Replace on the stack the current instance of the waterfall with a new instance,
// and start from the top.
return await stepContext.ReplaceDialogAsync(nameof(YOURMINIWATERFALLDIALOG), cancellationToken: cancellationToken);

}

这确实很粗糙,但足以让您大致了解我的意思。通过将您说失败的延续放入依赖于令牌的自己的if-check中,可以防止您在没有有效的延续的情况下继续前进,从而失败。