public virtual async Task StartAsync(IDialogContext context)
        {
            if (this.executionContextChain != null)
            {
                var childDialog = new LuisActionMissingEntitiesDialog(this.luisService, this.executionContextChain);

                // clean executionContextChain - avoid serialization payload
                this.executionContextChain = null;

                context.Call(childDialog, this.AfterContextualActionFinished);

                return;
            }

            await this.MessageReceivedAsync(context, null);
        }
        protected virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable <IMessageActivity> item)
        {
            var nextPromptIdx = 0;

            this.luisAction.IsValid(out ICollection <ValidationResult> validationResults);
            if (item != null)
            {
                var message    = await item;
                var paramName  = validationResults.First().MemberNames.First();
                var paramValue = message.Text;

                var result = await LuisActionResolver.QueryValueFromLuisAsync(this.luisService, this.luisAction, paramName, paramValue, context.CancellationToken);

                if (result.Succeed)
                {
                    nextPromptIdx++;
                }
                else if (!string.IsNullOrWhiteSpace(result.NewIntent) && result.NewAction != null)
                {
                    var currentActionDefinition = LuisActionResolver.GetActionDefinition(this.luisAction);

                    var isContextual = false;
                    if (LuisActionResolver.IsValidContextualAction(result.NewAction, this.luisAction, out isContextual))
                    {
                        var executionContextChain = new List <ActionExecutionContext> {
                            new ActionExecutionContext(result.NewIntent, result.NewAction)
                        };

                        var childDialog = new LuisActionMissingEntitiesDialog(this.luisService, executionContextChain);

                        context.Call(childDialog, this.AfterContextualActionFinished);

                        return;
                    }
                    else if (isContextual & !LuisActionResolver.IsContextualAction(this.luisAction))
                    {
                        var newActionDefinition = LuisActionResolver.GetActionDefinition(result.NewAction);

                        await context.PostAsync($"Cannot execute action '{newActionDefinition.FriendlyName}' in the context of '{currentActionDefinition.FriendlyName}' - continuing with current action");
                    }
                    else if (!this.luisAction.GetType().Equals(result.NewAction.GetType()))
                    {
                        var newActionDefinition = LuisActionResolver.GetActionDefinition(result.NewAction);

                        var valid = LuisActionResolver.UpdateIfValidContextualAction(result.NewAction, this.luisAction, out isContextual);
                        if (!valid && isContextual)
                        {
                            await context.PostAsync($"Cannot switch to action '{newActionDefinition.FriendlyName}' from '{currentActionDefinition.FriendlyName}' due to invalid context - continuing with current action");
                        }
                        else if (currentActionDefinition.ConfirmOnSwitchingContext)
                        {
                            // serialize overrun info
                            this.overrunData = result;

                            PromptDialog.Confirm(
                                context,
                                this.AfterOverrunCurrentActionSelected,
                                $"Do you want to discard the current action '{currentActionDefinition.FriendlyName}' and start executing '{newActionDefinition.FriendlyName}' action?");

                            return;
                        }
                        else
                        {
                            this.intentName = result.NewIntent;
                            this.luisAction = result.NewAction;

                            this.luisAction.IsValid(out validationResults);
                        }
                    }
                }
            }

            if (validationResults.Count > nextPromptIdx)
            {
                await context.PostAsync(validationResults.ElementAt(nextPromptIdx).ErrorMessage);

                context.Wait(this.MessageReceivedAsync);
            }
            else
            {
                context.Done(new ActionExecutionContext(this.intentName, this.luisAction));
            }
        }