Search code examples
c#botframeworkchatbotbot-framework-composer

How to call "BeginDialogAsync" method using a dialog defined in Bot Framework Composer


As the title says, I have my Bot created inside the Bot Framework Composer and would like to be able to manually call (BeginDialogAsync) those dialogs in C# inside something like a bot component where I have access to DialogContext.

Some context: The whole reason why I would want this is because, for whatever reason, there doesn't seem to be a way to use the composer action "Begin a new dialog" where I can assign it a property containing the name of the Dialog I wish to Start(Even though it has an "expression" type of input). The alternative is to predefine 60 different "Begin a new dialog" actions, which is not feasible.

I have googled this extensively and have found several solutions however none of them seem to be working for the newest version of Bot Framework Composer 2.x and Bot Framework SDK 4.x

Things I have tried usually revolved around loading the ".dialog" file using ResourceExplorer. My last ditch attempt was to load and cast that ".dialog" file as AdaptiveDialog, however that just throws the error: Could not create an instance of type Microsoft.Bot.Builder.Dialogs.Dialog. Type is an interface or abstract class and cannot be instantiated.

Sample code:

private void startDialogTest(DialogContext dc, CancellationToken cancellationToken, string dialogName)
{
    var dialogResource = _resourceExplorer.GetResource($"{dialogName}.dialog");
    var composerDialog = _resourceExplorer.LoadType<AdaptiveDialog>(dialogResource);

    dc.Dialogs.Add(composerDialog);

    dc.BeginDialogAsync(dialogName, cancellationToken: cancellationToken);
}

I understand why it happened because there is simply not enough information and it does not know what the heck to deserialize that Json into since Dialog is an abstract class.

If anybody has a sample code or a github link that does what I want I would be very grateful.


Solution

  • I have found a solution to my problem a few days ago.

    The reason why assiging a property to "Begin a new dialog" action did not work is not because the "expression input" itself didn't work but because doing it that way skips 1 crucial step for hoping to another dialog to even work at all.

    Inside that dialog json root(Click "Show code" option) you need to define an array containing the names of all dialogs you wish to be able to jump to.

    Example: Let's assume we have dialogs named TestDialogA, TestDialogB and TestDialogC.

    We want dialog TestDialogA to be able to able to start TestDialogB or TestDialogC. The way to do this is to open the json code of TestDialogA and at the root define a property called "dialogs" where you will insert TestDialogB and TestDialogC, like so:

    {
      "$kind": "Microsoft.AdaptiveDialog",
    ----------------------------------------------------------- Insert Here
      "dialogs": [
        "TestDialogB",
        "TestDialogC"
      ],
    ---------------------------------------------------------- Insert Here
      "$designer": {
        "id": "s8Uwor",
        "name": "TestDialogA",
        "comment": ""
      }
    

    This is actually what "Begin a new dialog" is suppose to do and is what it does when you manually hardcode/select a dialog but it does not do that if you send it a property containing the value of the Dialog you wish to jump to.

    Likely to do with it having to know what dialog "Begin a new dialog" will jump to during compile time and not runtime as then it is too late.

    This is a crucial step as without it TestDialogA does not even know that TestDialogB and TestDialogC exist. Same goes if you wish to jump to TestDialogA from TestDialogB.