Botbuilder-dotnet: ShowTypingMiddleware doesn't work when configured via AddBot (BotframeworkOptions)

Created on 13 Aug 2019  路  6Comments  路  Source: microsoft/botbuilder-dotnet

Version

4.5.1

Describe the bug

If ShowTypingMiddleware is added via AddBot configureAction, it doesn't work.
But if it's added to the adapter direclty via adapter.Use(new ShowTypingMiddleware()) it works.

To Reproduce

Steps to reproduce the behavior:

  1. Add the middleware via the below code. No typing event is sent.
services.AddBot<T>(options =>
{
    // Password
    options.CredentialProvider = credentialProvider;
    // Add typing middleware
    options.Middleware.Add(new ShowTypingMiddleware());
});
  1. Add the middleware via the below code in the adapter:
this.Use(new ShowTypingMiddleware());

Try emulator and now it works.

Expected behavior

It should work in both cases.

Bot Services Support customer-replied-to customer-reported

Most helpful comment

The middleware must be added to the Adapter that is being used, perhaps that is not happen. One thing we have seen recently is that old and new ways of initializing things are being mixed and this leads to some confusion.

Previously in our original samples we used this AddBot function to add a single bot in the ASP message handling path. However, following some feedback we modified this to align more directly with the ASP MVC Controller model. In this new world the Adapter is created explicitly and the Controller is given it through the ASP DI mechanism.

If you are using the new approach with an explicit Controller and an Adapter added to the services collection then the AddBot code is irrelevant because it is configuring a different Adapter that is never used behind the scenes.

So take care to not mix the old style "AddBot approach" with the new style "MVC approach."

All 6 comments

@sidecus I'm asking our support team to help you.

The middleware must be added to the Adapter that is being used, perhaps that is not happen. One thing we have seen recently is that old and new ways of initializing things are being mixed and this leads to some confusion.

Previously in our original samples we used this AddBot function to add a single bot in the ASP message handling path. However, following some feedback we modified this to align more directly with the ASP MVC Controller model. In this new world the Adapter is created explicitly and the Controller is given it through the ASP DI mechanism.

If you are using the new approach with an explicit Controller and an Adapter added to the services collection then the AddBot code is irrelevant because it is configuring a different Adapter that is never used behind the scenes.

So take care to not mix the old style "AddBot approach" with the new style "MVC approach."

Thanks. However I am not adding a singleton bot to the ASP message handling path. I am injecting a transient bot into the controller via Microsoft.Bot.Builder.Integration.AspNet.Core.ServiceCollectionExtensions.AddBot.

        // Remarks:
        //     The TBot will be registered as transient and be instantiated on each turn.
        public static IServiceCollection AddBot<TBot>(this IServiceCollection services, Action<BotFrameworkOptions> configureAction = null)

Below is part of my controller code:

        public BotController(IBotFrameworkHttpAdapter adapter, IBot bot)
        {
            this.adapter = adapter;
            this.bot = bot;
        }

        [HttpPost]
        public async Task PostAsync()
        {
            // Delegate the HTTP POST processing to adapter.
            // The adapter will invoke the bot as appropriate.
            await this.adapter.ProcessAsync(this.Request, this.Response, this.bot);
        }

I don't see that I am doing anything different from the "new path" you mentioned.

The issue is, Microsoft.Bot.Builder.Integration.AspNet.Core.ServiceCollectionExtensions.AddBot takes an Action<BotFrameworkOptions> parameter, and Middleware can be configured as part of the configuration. From the definition of BotFrameworkOptions:

        //
        // Summary:
        //     Gets a list of the Microsoft.Bot.Builder.IMiddleware to use on each incoming
        //     activity.
        public IList<IMiddleware> Middleware { get; }

Are you saying that we should never use this to configure any middle ware?

@sidecus, to reiterate what John wrote earlier, the recommended way of doing things nowadays is to _not_ to use the old setup way of using AddBot. And with whichever path you choose to head down, then it's important to not mix old ways of setting up a bot with newer methods


Recommended Bot Setup (MVC)

Instead you want to create the adapter explicitly. And you can add middleware to the pipeline calling BotFrameworkAdapter.Use():

Then in Startup.cs add that custom adapter as a singleton, which will be given to the Controller via DI:

The two linked bullets above are part of our robust Virtual Assistant sample built by our solutions team.

Additional reference to the Adapters in the SDK


The "Old Way" Using AddBot

If you do decide to go the route of using AddBot, be sure to not mix the old and new ways of setting up a bot.

  • Startup.cs using the proper setup for the old way

    • note that if you use AddBot, then you must call .UseBotFramework()

  • Also something to note is that this old way _does not use the controller model_. You can take a look at the scaffolding the linked DialogPromptBot sample of how you'd need to set your bot up if you want to use AddBot in your configuration

  • Another Older Sample using the ShowTypingMiddleware: Enterprise Bot Startup.cs File


All in all, the recommended method for setting up a bot is to explicitly create the adapter and give it to the Controller via DI as shown above.

If you choose to use the older method of setting up a bot, just take care to implement all the pieces to properly set it up

Ran a bot using the older setup with options.Middleware.Add(new ShowTypingMiddleware()); + UseBotFramework(), and the typing indicator works as expected.

Closing issue

thanks @Zerryth ! Now it's clear to me - I will use the new way and replace AddBot with AddTransient.

Was this page helpful?
0 / 5 - 0 ratings