简体   繁体   中英

Bot Framework V4 dependence injection not working

I am using .Net Core 2.1 to build a Bot with version 4 like the example here and I am not getting any response from the Bot Framework Emulator or code error from Visual Studio. When I go from url it says this error on image below. I think is something wrong with the dependency injection. What I am doing wrong?

在此处输入图片说明

On startup:

public class Startup
    {
        public Startup(IConfiguration configuration, IHostingEnvironment env)
        {
            Configuration = configuration;
            var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
            configuration = builder.Build();

        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            // Create the Bot Framework Adapter with error handling enabled.
            services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

            // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
           // services.AddTransient<IBot, MyBot>();

            // Create the credential provider to be used with the Bot Framework Adapter.
            services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();

            // Create the Bot Framework Adapter.

            // storage
            services.AddSingleton<IStorage, MemoryStorage>();

            // Create the User state. (Used in this bot's Dialog implementation.)
            services.AddSingleton<UserState>();

            services.AddSingleton<RootDialog>();
            services.AddTransient<IBot, DialogBot<RootDialog>>();

            // Create the Conversation state. (Used by the Dialog system itself.)
            services.AddSingleton<ConversationState>();

            services.AddSingleton(Configuration);

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseWebSockets();
            app.UseMvc();
            app.UseBotFramework();

        }
    }

In DialogBot.cs :

 public class DialogBot<T>: ActivityHandler where T : Dialog
    {
        protected readonly BotState ConversationState;
        protected readonly Dialog Dialog;
        protected readonly ILogger Logger;
        protected readonly BotState UserState;

        public DialogBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger)
        {
            ConversationState = conversationState;
            UserState = userState;
            Dialog = dialog;
            Logger = logger;
        }

        public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            await base.OnTurnAsync(turnContext, cancellationToken);

            // Save any state changes that might have occured during the turn.
            await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
            await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
        }

        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);
        }
        protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            foreach (var member in membersAdded)
            {
                if (member.Id != turnContext.Activity.Recipient.Id)
                {
                    await turnContext.SendActivityAsync(MessageFactory.Text($"Welcome!"), cancellationToken);
                }
            }
        }

In RootDialog.cs :

[Serializable]
    public class RootDialog : ComponentDialog
    {
        protected readonly ILogger _logger;
        protected readonly Dialog _dialog;
        protected readonly BotState _conversationState;
        protected readonly AdapterWithErrorHandler _adapterWithErrorHandler;
        protected readonly Encryption _encryption;
        private readonly IConfiguration _iConfiguration;


        public RootDialog(ConversationState conversationState, Dialog dialog,ILogger<RootDialog> Logger, AdapterWithErrorHandler AdapterWithErrorHandler, Encryption Encryption, IConfiguration configuration)
        {
            _conversationState = conversationState;
            _dialog = dialog;
            _logger = Logger;
            _adapterWithErrorHandler = AdapterWithErrorHandler;
            _encryption = Encryption;
            _iConfiguration = configuration;
        }

        const string HeroCard = "Hero Card";
        const string ThumbnailCard = "Thumbnail Card";

        private async Task<DialogTurnResult> StartDialogAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            // Start the child dialog. This will run the top slot dialog than will complete when all the properties are gathered.
            return await stepContext.BeginDialogAsync("slot-dialog", null, cancellationToken);
        }
}

Emulator:

在此处输入图片说明

Remove

Dialog dialog,

from your RootDialog .

It serves no purpose and the container is unaware of how to resolve it for injection into the target class.

RootDialog will thus refactor to

[Serializable]
public class RootDialog : ComponentDialog {
    protected readonly ILogger _logger;        
    protected readonly BotState _conversationState;
    protected readonly AdapterWithErrorHandler _adapterWithErrorHandler;
    protected readonly Encryption _encryption;
    private readonly IConfiguration _iConfiguration;

    public RootDialog(ConversationState conversationState, ILogger<RootDialog> logger, AdapterWithErrorHandler adapterWithErrorHandler, Encryption encryption, IConfiguration configuration) {
        _conversationState = conversationState;            
        _logger = logger;
        _adapterWithErrorHandler = adapterWithErrorHandler;
        _encryption = encryption;
        _iConfiguration = configuration;
    }

    const string HeroCard = "Hero Card";
    const string ThumbnailCard = "Thumbnail Card";

    private async Task<DialogTurnResult> StartDialogAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        // Start the child dialog. This will run the top slot dialog than will complete when all the properties are gathered.
        return await stepContext.BeginDialogAsync("slot-dialog", null, cancellationToken);
    }
}

Ensure that all explicit dependencies to be injected into the target class has been registered with the service collection and by extension the DI container.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM