r3plica r3plica - 22 days ago 13
C# Question

Microsoft Bot Framework forwarding to dialog is not working correctly

I have 2 Dialogs. In the first one I forward to the second one if the result matches my criteria, the code looks like this:

/// <summary>
/// Intent for choosing a category
/// </summary>
/// <param name="context">The current context</param>
/// <param name="result">The Luis result</param>
/// <returns></returns>
[LuisIntent("Choose category")]
public async Task ChooseCategory(IDialogContext context, LuisResult result)
{

// Get our category
var category = TryFindCategory(result);
var response = "The category you have chosen is not in the system just yet.";

switch (category)
{
case "camera":

// If our category is a camera, forward to our QuestionDialog
await context.Forward(new QuestionDialog(), ResumeAfter, new Activity { Text = result.Query }, CancellationToken.None);
break;
default:

// If we have an unknown category, update the response message
if (!string.IsNullOrEmpty(category)) response = $"Sorry, PiiiCK does not deal with { category.Pluralise() } just yet.";

// Post our response back to the user
await context.PostAsync(response);

// Execute the message recieved delegate
context.Wait(MessageReceived);
break;
}
}

/// <summary>
/// Delgate function for resuming after a response have been recieved from LUIS
/// </summary>
/// <param name="context">The current context</param>
/// <param name="result">The Luis result</param>
/// <returns></returns>
private async Task ResumeAfter(IDialogContext context, IAwaitable<object> result)
{
context.Wait(MessageReceived);
}


I have set my question dialog up like this:

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

// Private properties
private readonly QuestionGroupService _questionGroupService;
private IList<QuestionGroup> _questionGroups;

/// <summary>
/// Gets a list of QuestionGroups
/// </summary>
/// <returns>A list of QuestionGroups</returns>
public async Task<IList<QuestionGroup>> QuestionGroups() => _questionGroups ?? (_questionGroups = await _questionGroupService.ListAllAsync());

/// <summary>
/// Default constructor
/// </summary>
public QuestionDialog()
{
_questionGroupService = new QuestionGroupService(new UnitOfWork<DatabaseContext>());
}

/// <summary>
/// Start our response
/// </summary>
/// <param name="context">The current context</param>
/// <returns></returns>
public async Task StartAsync(IDialogContext context) => context.Wait(ActivityRecievedAsync);

/// <summary>
/// When our message is recieved we execute this delegate
/// </summary>
/// <param name="context">The current context</param>
/// <param name="result">The result object</param>
/// <returns></returns>
private async Task ActivityRecievedAsync(IDialogContext context, IAwaitable<object> result)
{

// Get our activity
var activity = await result as Activity;

// If it contains test
await context.PostAsync("This is my first question?");
context.Wait(GroupOneAnswerAsync);
}

/// <summary>
///
/// </summary>
/// <param name="context">The current context</param>
/// <param name="result">The result object</param>
/// <returns></returns>
private async Task GroupOneAnswerAsync(IDialogContext context, IAwaitable<object> result)
{

// Get our activity
var activity = await result as Activity;

// If it contains test
await context.PostAsync("This is my second question?");
context.Wait(GroupTwoAnswerAsync);
}

private async Task GroupTwoAnswerAsync(IDialogContext context, IAwaitable<object> result)
{

// Get our activity
var activity = await result as Activity;

// If it contains test
await context.PostAsync("This is my third question?");
context.Wait(GroupThreeAnswerAsync);
}

private async Task GroupThreeAnswerAsync(IDialogContext context, IAwaitable<object> result)
{

// Get our activity
var activity = await result as Activity;

// If it contains test
await context.PostAsync("This is my third question?");
context.Wait(GetResultsAsync);
}

private async Task GetResultsAsync(IDialogContext context, IAwaitable<object> result)
{

// Get our activity
var activity = await result as Activity;

// If it contains test
await context.PostAsync("These are my results");
context.Wait(ActivityRecievedAsync);
}
}


When I test this, when the first Dialog forwards to the second one, it invokes the StartAsync method, but ActivityRecievedAsync is never invoked.
Does anyone know why?

Answer

Per the discussion you have in the chat, make sure you are running the latest version of the BotBuilder as we might be hitting a known issue in a previous version.

Also (not related to the issue, but as a good practice) you might want to change the signature of

private async Task ActivityRecievedAsync(IDialogContext context, IAwaitable<object> result)

to

private async Task ActivityRecievedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)

Having your dialog being IDialog it doesn't dictate that the very first input of the dialog has to be a object. It just says that the

Also, you can use the incoming message that went to LUIS to do the forward instead of manually creating the activity (see this). Just change the signature of the intent method to

public async Task ChooseCategory(IDialogContext context, IAwaitable<IMessageActivity> activity, LuisResult result)

await the activity parameter and use that in the context.Forward

Some interesting resources: