1

I am working on BOT Framework(C#), I am facing one issue and need your help. Below code is for showing the carousel of Hero card and on the selection of one of Hero Card I want to call a callback method, in below example you can see OnCardSelection is the method which I want to call on Card selection, but on execution of line context.Wait(onCardSelection) i am getting below error

invalid need: expected Call, have Wait

and may be due to this it is ending the conversation and consider further action (Click on Hero card) as a new conversation. Also, I want to access details of the card in OnCardSelection method. How to achieve this. Thank you.

[LuisModel("your sub key", "secret")]
[Serializable]
public class BotManager : LuisDialog<object>
{
    public async Task RaiseTicket(IDialogContext context, LuisResult result)
    {
     PromptDialog.Confirm(
                    context: context,
                    resume: ResumeAndHandleConfirmRaiseTicketAsync,
                    prompt: "It looks like you want to raise a ticket. Do you want to continue?",
                    retry: "I didn't understand. Please try again.");
    }


    private async Task ResumeAndHandleConfirmRaiseTicketAsync(IDialogContext context, IAwaitable<bool> argument)
    {
        bool choicesAreCorrect = await argument;
        if (choicesAreCorrect)
        {
           RaiseTicket objRaiseTicket = new RaiseTicket();
           await objRaiseTicket.StartAsync(context);
        }
        else
        {
           await context.PostAsync("Okay");
        }
    }
}

[Serializable]
public class RaiseTicket
{
       public async Task StartAsync(IDialogContext context)
       {
          TypeOfTicket typeOfTicket;
          context.UserData.TryGetValue("TypeOfTicket", out typeOfTicket);
          if (typeOfTicket == TypeOfTicket.None)
          {
              //RaiseTicket
          }
          else
          {
              await PickExactCategory(context);
          }
       }

        public async Task PickExactCategory(IDialogContext context)
        {
            var message = context.MakeMessage();
            message.AttachmentLayout = AttachmentLayoutTypes.Carousel;
            message.Attachments = GetCardsAttachments(categoryList);
            await context.PostAsync(message);
            context.Wait(OnCardSelection);
        }


        protected async Task OnCardSelection(IDialogContext context, IAwaitable<IMessageActivity> result)
        {
             var answer = await result;
             context.Done(new object());
        }

        private IList<Attachment> GetCardsAttachments(Categorylist[] categoryList)
        {
            List<Attachment> lstAttachment = new List<Attachment>();
            foreach (Categorylist item in categoryList)
            {
               lstAttachment.Add(GetHeroCard(
               item.Title, item.SubTitle,item.Text,
               new CardAction(ActionTypes.ImBack, "Select", value: item.Tier3)));
            }
           return lstAttachment;
        }

        private static Attachment GetHeroCard(string title, string subtitle, string text, CardAction cardAction)
        {
            var heroCard = new HeroCard
            {
              Title = title,
              Subtitle = subtitle,
              Text = text,
              Buttons = new List<CardAction>() { cardAction },
            };
        return heroCard.ToAttachment();
        }
    }
Amol Pawar
  • 251
  • 1
  • 15
  • Is your code embedded in a dialog? I tried to complete your code inside a dialog, it works fine by my side. If it is needed, I can give you my code sample as an answer below. – Grace Feng Jan 15 '18 at 07:32
  • Hi Grace, Thank you for taking out your time to read the problem.The code is embedded in the dialog. I have edited the post and added the rest of the code. It will be great if you share your code. – Amol Pawar Jan 15 '18 at 11:39
  • have you checked my answer, any update? – Grace Feng Jan 18 '18 at 01:19

2 Answers2

0

The problem is because how you are trying to call your child dialog RaiseTicket.

First of all, if it is a dialog it should implement the IDialog interface.

Then you will have to call or forward a message to the dialog. You shouldn't manually call the StartAsync method.

You can read Handling multiple dialogs in Microsoft bot framework or Calling Forms from Dialogs to understand more how the Call / Forward methods work. Also, you can review the Manage conversation flow with dialogs article from the documentation.

Ezequiel Jadib
  • 14,767
  • 2
  • 38
  • 43
0

As Ezequiel Jadib said, problem is how you call the RaiseTicket, and RaiseTicket should implement the IDialog interface.

You can modify the RaiseTicket for example like this:

[Serializable]
public class RaiseTicket: IDialog<object>
{

    public Task StartAsync(IDialogContext context)
    {
        context.Wait(PickExactCategory);
        return Task.CompletedTask;
    }

    public async Task PickExactCategory(IDialogContext context, IAwaitable<object> result)
    {
        var message = context.MakeMessage();
        message.AttachmentLayout = AttachmentLayoutTypes.Carousel;
        message.Attachments = GetCardsAttachments(categoryList);
        await context.PostAsync(message);
        context.Wait(OnCardSelection);
    }

    public async Task OnCardSelection(IDialogContext context, IAwaitable<object> result)
    {
        var answer = await result as IMessageActivity;
        context.Done(new object());
    }

    private IList<Attachment> GetCardsAttachments(List<Categorylist> categoryList)
    {
        List<Attachment> lstAttachment = new List<Attachment>();
        foreach (Categorylist item in categoryList)
        {
            lstAttachment.Add(GetHeroCard(
            item.Title, item.SubTitle, item.Text,
            new CardAction(ActionTypes.ImBack, "Select", value: item.Tier3)));
        }
        return lstAttachment;
    }

    private static Attachment GetHeroCard(string title, string subtitle, string text, CardAction cardAction)
    {
        var heroCard = new HeroCard
        {
            Title = title,
            Subtitle = subtitle,
            Text = text,
            Buttons = new List<CardAction>() { cardAction },
        };
        return heroCard.ToAttachment();
    }
}

Then call this RaiseTicket dialog in your BotManager for example like this:

var dialog = new RaiseTicket();
await context.Forward(dialog, dialog.OnCardSelection, null, CancellationToken.None);
Grace Feng
  • 16,564
  • 2
  • 22
  • 45