如何在取消scorable中检测顶级bot框架对话框

时间:2017-07-10 23:48:05

标签: c# botframework

我正在使用取消scorable来捕获关键字quit和cancel,并且我使用Task.Fail来使当前对话框失败。该示例使用Task.Reset但是展开整个堆栈,这在多级堆栈中是不可取的。

所以Task.Fail工作正常,我抛出一个OperationCanceledException并在调用对话框中吞下它然而我的问题是如果我失败顶级对话框然后我的机器人崩溃。

我如何判断我是否处于可靠的堆栈顶部(在这种情况下我将忽略该消息)或者是否有更好的方法来处理取消单个对话框?

请注意,我看到有一个Frames集合已经通过了,我想也许可以帮助但是在顶层设置为4而不是我想象的0,我不确定这是否是可靠的来源?

这是我对根对话框的实例化

    internal static IDialog<object> MakeRootDialog()
    {
        return Chain.From(() => new LuisDialogHome())
            .Do(async (context, dialog) =>
            {
                try
                {
                    await dialog;
                }
                catch (Exception e)
                {
                    await context.PostAsync($"Error from home dialog: {e.Message}");
                }
            });
    }

    protected override async Task PostAsync(IActivity item, string state, CancellationToken token)
    {
        // This will unwind the entire stack and take you right back to the top which we dont want so Fail the task instead to undo one layer
        //            this.task.Reset();
        this.task.Fail(new OperationCanceledException($"Cancelled"));
    }

我的可取消问题task.Fail会导致上面的异常处理程序被调用,而且很抱歉,我的机器人代码有问题。&#39;消息被发送给用户。

1 个答案:

答案 0 :(得分:0)

这就是我做的方式,我为#34;取消&#34;这种方式可以从对话的任何一点开始。 Also here is a good simple video to watch

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<select mutiple size="3">
  <option id="option1" selected value="1"> Option 1</option>
  <option id="option2" value="2"> Option 2</option>
  <option id="option3" value="3"> Option 3</option>
</select>

<p id="p1"> Thanks for choosing option 1</p>
<p id="p2"> Thanks for choosing option 2</p>
<p id="p3"> Thanks for choosing option 3</p>

然后在我的消息控制器中我构建了一个特殊情况来处理它, namespace PizzaBot.Dialogs { using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Bot.Builder.Dialogs.Internals; using Microsoft.Bot.Builder.Internals.Fibers; using Microsoft.Bot.Connector; using Microsoft.Bot.Builder.Scorables.Internals; public class CancelScorable : ScorableBase<IActivity, string, double> { private readonly IDialogTask task; public CancelScorable(IDialogTask task) { SetField.NotNull(out this.task, nameof(task), task); } protected override async Task<string> PrepareAsync(IActivity activity, CancellationToken token) { var message = activity as IMessageActivity; if (message != null && !string.IsNullOrWhiteSpace(message.Text)) { if (message.Text.Equals("cancel", StringComparison.InvariantCultureIgnoreCase)) { return message.Text; } } return null; } protected override bool HasScore(IActivity item, string state) { return state != null; } protected override double GetScore(IActivity item, string state) { return 1.0; } protected override async Task PostAsync(IActivity item, string state, CancellationToken token) { this.task.Reset(); } protected override Task DoneAsync(IActivity item, string state, CancellationToken token) { return Task.CompletedTask; } } } 从一开始就启动机器人:

await SendGetStarted(iActivity, activity);

你也需要在你的Golbal.asax

中添加这样的东西
    public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{

    if (activity.Type == ActivityTypes.Message)
    {               
        try
        {
           await Conversation.SendAsync(activity, () => new RootDialog(activity.ChannelId));
        }
        catch (Exception e)
        {
            IActivity iActivity = activity as IActivity;
            await SendGetStarted(iActivity, activity);
        }
    }
    else
    {
        await HandleSystemMessage(activity);
    }
    if (activity.Text == "cancel")
    {
        IActivity iActivity = activity as IActivity;
        await SendGetStarted(iActivity, activity);
    }
    var response = this.Request.CreateResponse(HttpStatusCode.OK);
    return response;
}