如何捕获从FormFlow对话框引发的异常?

时间:2018-06-21 10:19:52

标签: botframework bots

我有一个使用FormFlow技术编写的漫游器对话框。

这里是BuildForm方法,用于建立对话框...

public static IForm<CarValuationDialog> BuildForm()
{
    var builder = new FormBuilder<CarValuationDialog>();

    Configure(builder);

    return new FormBuilder<CarValuationDialog>()
        .Field(nameof(ValuationOption))
        .Field(nameof(RegistrationNumber))
        .Field(nameof(Mileage))
        .Field(
            nameof(PreviousOwnerOption),
            active: carValuation => carValuation.ValuationOption == ValuationOptions.LookingToSell)
        .Field(
            nameof(ServiceHistoryOption),
            active: carValuation => carValuation.ValuationOption == ValuationOptions.LookingToSell)
        .OnCompletion(GetValuationAndDisplaySummaryToUser)
        .Confirm(Confirmation)
        .Build();
}

我遇到的问题是如何在步骤中捕获异常,以便可以向用户发送自定义消息(以替换默认的“抱歉,我的机器人代码有问题。”文本)并重新启动过程回到第一个问题?

在搜索车辆的方法中,如果没有找到车辆,那么我想抛出一个异常。我已经尝试了以下方法。

context.Fail(new FormCanceledException<CarValuationDialog>($"There was a problem retrieving information about the vehicle '{state.RegistrationNumber}'."));

throw new FormCanceledException<CarValuationDialog>($"There was a problem retrieving information about the vehicle '{state.RegistrationNumber}'.");

关于context.Fail(),我不确定在那之后我需要调用什么,因为bot代码构成了正常执行到最后的过程。看来我需要在致电context.Fail()之后再打电话。

抛出异常的确可行,因为代码停止了,但是没有什么可以捕捉到该异常的。我尝试在MessagesController

中执行此操作
internal static IDialog<CarValuationDialog> MakeRootDialog()
{
    return Chain
        .From(() => FormDialog.FromForm(CarValuationDialog.BuildForm).DefaultIfException())
        .Do(async (context, carValuationDialog) =>
        {
            try
            {
                var completed = await carValuationDialog;
            }
            catch (FormCanceledException<CarValuationDialog> e)
            {
                string reply = string.Empty;

                reply = e.Message;

                await context.PostAsync(reply);
            }
        })
        .Catch((dialog, exception) =>
            {
                var foo = exception.Message;

                return dialog;
            });
}

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
    if (activity.GetActivityType() == ActivityTypes.Message)
    {
        await Conversation.SendAsync(activity, MakeRootDialog);
    }
    else
    {
        HandleSystemMessage(activity);
    }

    return Request.CreateResponse(HttpStatusCode.OK);
}

但是没有异常处理程序被执行。

有人可以指出我正确的方向吗?

1 个答案:

答案 0 :(得分:3)

试试这个-

消息控制器

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
    if (activity.Type == ActivityTypes.Message)
    {
        await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
    }
    else
    {
        HandleSystemMessage(activity);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK);
    return response;
}

并添加一个新的类“根对话框”:

根对话框

public Task StartAsync(IDialogContext context)
{
    context.Wait(MessageReceivedAsync);

    return Task.CompletedTask;
}

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
    var message = await result;
    FormDialog<CustomerDetails> customerForm = new FormDialog<CustomerDetails>(new CustomerDetails(), CustomerDetails.BuildForm, FormOptions.PromptInStart);
    context.Call(customerForm, FormSubmitted);
}

public async Task FormSubmitted(IDialogContext context, IAwaitable<CustomerDetails> result)
{
    try
    {
        var form = await result;
        await context.PostAsync("Thanks for your response.");
    }
    catch (FormCanceledException<SoftwareRequest> e)
    {
        string reply;
        if (e.InnerException == null)
        {
            reply = $"Thanks for filling out the form.";

        }
        else
        {
            reply = $"Sorry, I've had a short circuit.  Please try again.";
        }
        context.Done(true);
        await context.PostAsync(reply);
    }
}

注意

请将CustomerDetails更改为表单类的名称。