Manage dialog complexity
APPLIES TO: SDK v4
With component dialogs, you can create independent dialogs to handle specific scenarios, breaking a large dialog set into more manageable pieces. Each of these pieces has its own dialog set, and avoids any name collisions with the dialog sets outside of it. Component dialogs are reusable in that they can be:
- Added to another
ComponentDialog
orDialogSet
in your bot. - Exported as a part of a package.
- Used within other bots.
Note
The Bot Framework JavaScript, C#, and Python SDKs will continue to be supported, however, the Java SDK is being retired with final long-term support ending in November 2023.
Existing bots built with the Java SDK will continue to function.
For new bot building, consider using Microsoft Copilot Studio and read about choosing the right copilot solution.
For more information, see The future of bot building.
Prerequisites
- Knowledge of bot basics, the dialogs library, and how to manage conversations.
- A copy of the multi-turn prompt sample in C#, JavaScript, Java, or Python.
About the sample
In the multi-turn prompt sample, we use a waterfall dialog, a few prompts, and a component dialog to create an interaction that asks the user a series of questions. The code uses a dialog to cycle through these steps:
Steps | Prompt type |
---|---|
Ask the user for their mode of transportation | Choice prompt |
Ask the user for their name | Text prompt |
Ask the user if they want to provide their age | Confirm prompt |
If they answered yes, ask for their age | Number prompt with validation to only accept ages greater than 0 and less than 150. |
Ask if the collected information is "ok" | Reuse Confirm prompt |
Finally, if they answered yes, display the collected information; otherwise, tell the user that their information won't be kept.
Implement your component dialog
In the multi-turn prompt sample, we use a waterfall dialog, a few prompts, and a component dialog to create an interaction that asks the user a series of questions.
A component dialog encapsulates one or more dialogs. The component dialog has an inner dialog set, and the dialogs and prompts that you add to this inner dialog set have their own IDs, visible only from within the component dialog.
To use dialogs, install the Microsoft.Bot.Builder.Dialogs NuGet package.
Dialogs\UserProfileDialog.cs
Here the UserProfileDialog
class derives from the ComponentDialog
class.
public class UserProfileDialog : ComponentDialog
Within the constructor, the AddDialog
method adds dialogs and prompts to the component dialog. The first item you add with this method is set as the initial dialog. You can change the initial dialog by explicitly setting the InitialDialogId
property. When you start a component dialog, it will start its initial dialog.
public UserProfileDialog(UserState userState)
: base(nameof(UserProfileDialog))
{
_userProfileAccessor = userState.CreateProperty<UserProfile>("UserProfile");
// This array defines how the Waterfall will execute.
var waterfallSteps = new WaterfallStep[]
{
TransportStepAsync,
NameStepAsync,
NameConfirmStepAsync,
AgeStepAsync,
PictureStepAsync,
SummaryStepAsync,
ConfirmStepAsync,
};
// Add named dialogs to the DialogSet. These names are saved in the dialog state.
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new NumberPrompt<int>(nameof(NumberPrompt<int>), AgePromptValidatorAsync));
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
AddDialog(new AttachmentPrompt(nameof(AttachmentPrompt), PicturePromptValidatorAsync));
// The initial child Dialog to run.
InitialDialogId = nameof(WaterfallDialog);
}
The following code represents the first step of the waterfall dialog.
private static async Task<DialogTurnResult> NameStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["transport"] = ((FoundChoice)stepContext.Result).Value;
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("Please enter your name.") }, cancellationToken);
}
For more information on implementing waterfall dialogs, see how to implement sequential conversation flow.
At run-time, the component dialog maintains its own dialog stack. When the component dialog is started:
- An instance is created and added to the outer dialog stack
- It creates an inner dialog stack that it adds to its state
- It starts its initial dialog and adds that to the inner dialog stack.
The parent context sees the component as the active dialog. However, to the context inside the component, it looks like the initial dialog is the active dialog.
Call the dialog from your bot
In the outer dialog set, the one to which you added the component dialog, the component dialog has the ID that you created it with. In the outer set, the component looks like a single dialog, much like prompts do.
To use a component dialog, add an instance of it to the bot's dialog set.
Bots\DialogBot.cs
In the sample, this is done using the RunAsync
method that is called from the bot's OnMessageActivityAsync
method.
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
Logger.LogInformation("Running dialog with Message Activity.");
// Run the Dialog with the new message Activity.
await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
}
Test your bot
- If you haven't done so already, install the Bot Framework Emulator.
- Run the sample locally on your machine.
- Start the Emulator, connect to your bot, and send messages as shown below.
Additional information
How cancellation works for component dialogs
If you call cancel all dialogs from the component dialog's context, the component dialog will cancel all of the dialogs on its inner stack and then end, returning control to the next dialog on the outer stack.
If you call cancel all dialogs from the outer context, the component is canceled, along with the rest of the dialogs on the outer context.
Next steps
Learn how to create complex conversations that branch and loop.