Reputation: 29186
I have a bot dialog written using the FormFlow technique.
Here is the BuildForm
method that builds the dialog...
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();
}
The issue I have is how to catch exceptions during the steps, so that I can send a custom message to the user (to replace the default 'Sorry, my bot code is having an issue.' text) and restart the process by going back to the first question?
In the method that searches for a vehicle, if no vehicle is fo8nd then I'd like to throw an exception. I've tried the following..
context.Fail(new FormCanceledException<CarValuationDialog>($"There was a problem retrieving information about the vehicle '{state.RegistrationNumber}'."));
and
throw new FormCanceledException<CarValuationDialog>($"There was a problem retrieving information about the vehicle '{state.RegistrationNumber}'.");
Regards context.Fail()
I'm not sure what I need to call after that, since the bot code contuinues to execute as per normal to the end. It looks like I need to call something else after the call to context.Fail()
.
Throwing the exception does work, as in the code stops, but there is nothing to catch that exception. I've tried doing this in the 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);
}
But none of the exception handlers are executed.
Can someone point me in the right direction please?
Upvotes: 1
Views: 151
Reputation: 1153
Try this-
Message Controller
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;
}
And add a new class Root Dialog:
Root Dialog
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);
}
}
NOTE
Please change CustomerDetails to the name of your form class.
Upvotes: 3