Mona Ghanathe
Mona Ghanathe

Reputation: 1

I get invalid need: expected Wait, have None in my Bot code

I get "invalid need: expected Wait, have None" exception in RootDialog, MessageReceivedAsync method's context.Forward line. Why could this be happening? what correction should I make? Please find my code below.

I use -C#, Visual Studio 2015, Microsoft Bot Framework, Bot emulator. This is for Web Chat.

MessageController

 public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
    {
        ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
        if (activity.Type == ActivityTypes.Message)
        {
            await Conversation.SendAsync(activity, () => new RootDialog());
        }
        else
        if (activity.Type == ActivityTypes.ConversationUpdate)
        {
            var greeting = activity.CreateReply("Hi! I'm Cmon. Enter the Id of the Employee you want to know about.");
            await connector.Conversations.ReplyToActivityAsync(greeting);
        }
        else
        {
            this.HandleSystemMessage(activity);
        }

        var response = Request.CreateResponse(HttpStatusCode.OK);
        return response;
    }

RootDialog -

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

    public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
    {
        var message = await result;
        try
        {
            if (message.Text != null)
            {
                await context.Forward(new DirectoryDialog(), null, message,CancellationToken.None);
            }

        }
        catch (Exception ex)
        {
            await context.PostAsync($"Oops! Something went wrong :-(");
        }
    }

DirectoryDialog -

public async Task StartAsync(IDialogContext context)
    {
        var message = context.Activity as IMessageActivity;
        var query = DirectoryQuery.Parse(message.Text);
        await context.PostAsync($"Searching for {query.SearchKey}...");

        try
        {
            await SearchEmployee(context, query);
        }
        catch (FormCanceledException ex)
        {
            await context.PostAsync($"Oops! Something went wrong :-(");
        }
    }

    private async Task SearchEmployee(IDialogContext context, DirectoryQuery searchQuery)
    {
        DirectoryDal dal = new DirectoryDal();
        DataSet ds = dal.GetEmployeeSearch(searchQuery.SearchKey);
        if (ds.Tables.Count > 0 & ds.Tables[0].Rows.Count > 0)
        {
            StringBuilder employeeSearchMessageBuilder = new StringBuilder(100);
//do something with data table data
            var employeeSearchReply = context.MakeMessage();
            employeeSearchReply.Type = ActivityTypes.Message;
            employeeSearchReply.TextFormat = TextFormatTypes.Markdown;
            employeeSearchReply.Text = employeeSearchMessageBuilder.ToString();
            await context.PostAsync(employeeSearchReply);

        }
    }

Upvotes: 0

Views: 234

Answers (3)

Nicolas R
Nicolas R

Reputation: 14609

By passing null here:

await context.Forward(new DirectoryDialog(), null, message,CancellationToken.None);

you are breaking the dialog chain. You have to define your Resume method.

The Troubleshooting section of the documentation has a good section about that, here:

Ensure all dialog methods end with a plan to handle the next message.

All IDialog methods should complete with IDialogStack.Call, IDialogStack.Wait, or IDialogStack.Done. These IDialogStack methods are exposed through the IDialogContext that is passed to every IDialog method. Calling IDialogStack.Forward and using the system prompts through the PromptDialog static methods will call one of these methods in their implementation.

Upvotes: 1

Tanmoy
Tanmoy

Reputation: 55

context.wait(MessageReceivedAsync);

at the end of MessageReceivedAsync(IDialogContext context, IAwaitable result) method of Root Dialog.

and

context.done(true);

at the end of StartAsync method of DirectoryDialog or within both try and catch block

Upvotes: 0

Mona Ghanathe
Mona Ghanathe

Reputation: 1

I was able to resolve the issue by making the following modifications to my DirectoryDialog.

DirectoryDialog code -

public async Task StartAsync(IDialogContext context)
    {
        var message = context.Activity as IMessageActivity;
        var query = DirectoryQuery.Parse(message.Text);
        await context.PostAsync($"Searching for {query.SearchKey}...");
        try
        {
            //await SearchEmployee(context, query);
            context.Wait(MessageReceivedAsync);
        }
        catch (FormCanceledException ex)
        {
            await context.PostAsync($"Oops! Something went wrong :-(");
        }
    }

RootDialog code -

public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
    {
        var message = await result;
        try
        {
            if (message.Text != null)
            {
                await context.Forward(new DirectoryDialog(), ResumeAfterOptionDialog, message,CancellationToken.None);
            }
        }
        catch (Exception ex)
        {
            await context.PostAsync($"Oops! Something went wrong");
        }

     finally{
        context.Done(true);
    }
    } 

    private async Task ResumeAfterOptionDialog(IDialogContext context, IAwaitable<object> result)
    {
        context.Wait(MessageReceivedAsync);
                }

Thank you Tanmoy and Nicolas for helping! :)

Upvotes: 0

Related Questions