Search code examples
c#botframework

Microsoft Bot Framework V4: System.NullReferenceException: 'Unable to locate SkillConversationIdFactoryBase in HostContext'


I am working on creating a workflow which allows composer created dialogs to be integrated into a bot skill project.

To accomplish this I am trying to follow the instructions in this post: https://microsoft.github.io/botframework-solutions/skills/handbook/experimental-add-composer/

My composer created dialogs including calling a skill. When I initiate that intent through the Bot Emulator I get this error:

System.NullReferenceException: 'Unable to locate SkillConversationIdFactoryBase in HostContext'

The setup to get to this error is time consuming so I have created a git repo which can be started fairly easily to demonstrate the issue.

The project can be found here: https://github.com/silverbulletgt/Integrate-Composer-Dialog-Using-Skill

To recreate the issue:

Prerequisites

Step to Recreate the Issue

  1. Open the solution file in visual studio Integrate-Composer-Dialog-Using-Skill.sln

  2. Put a breakpoint on line 72 of DefaultAdapter.cs - this is where the error can be seen

  3. Start debugging the project

  4. Open Bot Emulator

  5. Connect to the bot: http://localhost:3978/api/messages

  6. Type "Greeting"

  7. Bot should respond with "Hello, I have recognized that you said greeting" - This means that the composer dialog integration is working as expected.

  8. Type "Skill"

  9. The breakpoint on line 72 of DefaultAdapter.cs should trigger giving details of the error.

Error & stack trace can be found here: https://github.com/silverbulletgt/Integrate-Composer-Dialog-Using-Skill/blob/master/Readme/error%20stack%20trace.txt

Edit:

I was able to compile the Bot Builder code Bot Builder GitHub & connect it to my project so that I could debug. I found the error to be happening on line 157 of Microsoft.Bot.Builder.Dialogs.Adaptive.BeginSkill.cs code BeginSkill.cs.

This line is trying to get the SkillConversationFactoryBase out of the dialogContext.Context.TurnState. I'm investigating how I might add this so that it is populated when this code executes.


Solution

    1. Fix: System.NullReferenceException: 'Unable to locate SkillConversationIdFactoryBase in HostContext' in Microsoft.Bot.Builder.Dialogs.Adaptive.Actions.BeginSkill

    This error was being caused by missing dependency injection requirements. Added the below lines to Startup.cs

    services.AddSingleton<SkillConversationIdFactoryBase, SkillConversationIdFactory>();
    services.AddSingleton<HttpClient>(new HttpClient());
    services.AddSingleton<BotFrameworkClient, BotFrameworkHttpClient>();
    

    Added to DefaultAdapter.cs

    New Field

    private readonly SkillConversationIdFactoryBase _skillConversationIdFactoryBase;
    

    New constructor parameters

    SkillConversationIdFactoryBase skillConversationIdFactoryBase,
    BotFrameworkClient botFrameworkClient
    

    To the body of the constructor

    _skillConversationIdFactoryBase = skillConversationIdFactoryBase;
    
    Use(new RegisterClassMiddleware<SkillConversationIdFactoryBase>(_skillConversationIdFactoryBase));
    Use(new RegisterClassMiddleware<BotFrameworkClient>(botFrameworkClient));
    

    This fixed the initial exception however there was then a new exception when the skill was called.

    Exception wasOperation returned an invalid status code 'NotFound' at Microsoft.Bot.Connector.Conversations.d__10.MoveNext()

    1. Fixing Operation returned an invalid status code 'NotFound' This exception was occurring because there was no endpiont api/skills. I suppose that the Bot Composer adds this endpoint automatically somehow.

    I added SkillController.cs based on the example here: Bot Builder Tests JSON SkillController

    Then added dependency injection to support the controller. Added to Startup.cs

    services.AddSingleton<ChannelServiceHandler, SkillHandler>();
                services.AddSingleton<BotAdapter>(sp => (BotFrameworkHttpAdapter)sp.GetService<IBotFrameworkHttpAdapter>());
    

    I tested a basic intent which does not use a skill to determine if there would be any conflict with the dependency injection impacting those. The basic intent worked as expected though.

    I updated the master branch with the changes Project Repo