2

I'm starting a project for a ChatBot in C# with the bot framework.

I choose the ContosoFlowers example for learning about the use of bot framework. In the AddressDialog users cannot quit the dialog after they enter to it without providing an address.

How can I update the code so when users reply "Cancel" or "Abort" or "B" or "Back" they quit the dialog?

namespace ContosoFlowers.BotAssets.Dialogs
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Extensions;
    using Microsoft.Bot.Builder.Dialogs;
    using Microsoft.Bot.Connector;
    using Properties;
    using Services;

    [Serializable]
    public class AddressDialog : IDialog<string>
    {
        private readonly string prompt;
        private readonly ILocationService locationService;

        private string currentAddress;

        public AddressDialog(string prompt, ILocationService locationService)
        {
            this.prompt = prompt;
            this.locationService = locationService;
        }

        public async Task StartAsync(IDialogContext context)
        {
            await context.PostAsync(this.prompt);
            context.Wait(this.MessageReceivedAsync);
        }

        public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
        {
            var message = await result;

            var addresses = await this.locationService.ParseAddressAsync(message.Text);
            if (addresses.Count() == 0)
            {

                await context.PostAsync(Resources.AddressDialog_EnterAddressAgain);
                context.Wait(this.MessageReceivedAsync);
            }
            else if (addresses.Count() == 1)
            {
                this.currentAddress = addresses.First();
                PromptDialog.Choice(context, this.AfterAddressChoice, new[] { Resources.AddressDialog_Confirm, Resources.AddressDialog_Edit }, this.currentAddress);
            }
            else
            {
                var reply = context.MakeMessage();
                reply.AttachmentLayout = AttachmentLayoutTypes.Carousel;

                foreach (var address in addresses)
                {
                    reply.AddHeroCard(Resources.AddressDialog_DidYouMean, address, new[] { new KeyValuePair<string, string>(Resources.AddressDialog_UseThisAddress, address) });
                }

                await context.PostAsync(reply);
                context.Wait(this.MessageReceivedAsync);
            }
        }

        private async Task AfterAddressChoice(IDialogContext context, IAwaitable<string> result)
        {
            try
            {
                var choice = await result;

                if (choice == Resources.AddressDialog_Edit)
                {
                    await this.StartAsync(context);
                }
                else
                {
                    context.Done(this.currentAddress);
                }
            }
            catch (TooManyAttemptsException)
            {
                throw;
            }
        }
    }

}
1
  • 3
    Tasks are a part of .NET, they have nothing to do with bots. Google for task cancellation, CancellationToken etc. Be aware though that cancelling a task that awaits a response from a remote service does NOT send any specific message to that service. It simply cancels the wait. If you want to tell the Bot service to terminate a dialog, you need to find and call the proper methods. Commented Dec 5, 2016 at 11:48

1 Answer 1

4

You just need to handle the quit conditions at the top of the MessageReceivedAsync method.

At the top of the dialog you can add something like

private static IEnumerable<string> cancelTerms = new[] { "Cancel", "Back", "B", "Abort" };

And also add this method:

public static bool IsCancel(string text)
{
   return cancelTerms.Any(t => string.Equals(t, text, StringComparison.CurrentCultureIgnoreCase));
}

Then is just a matter of understanding if the message sent by the user matches any of the cancelation terms. In the MessageReceivedAsync method do something like:

public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
   var message = await result;

   if (IsCancel(message.Text)) 
   {
     context.Done<string>(null);
   }

   // rest of the code of this method..
}

You can also go a bit more generic and create a CancelableIDialog similar to what was done in the CancelablePromptChoice.

Sign up to request clarification or add additional context in comments.

1 Comment

try 'context.Done<string>(null);'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.