public void ConfigureServices()

in templates/csharp/VA/VA/Startup.cs [53:166]


        public void ConfigureServices(IServiceCollection services)
        {
            // Configure MVC
            services.AddControllers().AddNewtonsoftJson();

            services.AddSingleton(Configuration);

            // Load settings
            var settings = new BotSettings()
            {
                LogPersonalData = Configuration.GetSection("logPersonalInfo")?.Value.ToLower() == "true"
            };
            Configuration.Bind(settings);
            services.AddSingleton(settings);

            // Configure channel provider
            services.AddSingleton<IChannelProvider, ConfigurationChannelProvider>();

            // Configure configuration provider
            services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();

            // Register the skills configuration class.
            var skillsConfig = new SkillsConfiguration(Configuration);
            services.AddSingleton(skillsConfig);

            // Register AuthConfiguration to enable custom claim validation.
            var allowedCallers = (from skill in skillsConfig.Skills.Values select skill.AppId).ToList();
            services.AddSingleton(sp => new AuthenticationConfiguration { ClaimsValidator = new AllowedCallersClaimsValidator(allowedCallers) });

            // Configure telemetry
            services.AddApplicationInsightsTelemetry();
            services.AddSingleton<IBotTelemetryClient, BotTelemetryClient>();
            services.AddSingleton<ITelemetryInitializer, OperationCorrelationTelemetryInitializer>();
            services.AddSingleton<ITelemetryInitializer, TelemetryBotIdInitializer>();
            services.AddSingleton<TelemetryInitializerMiddleware>();
            
            services.AddSingleton<TelemetryLoggerMiddleware>(s => new TelemetryLoggerMiddleware(s.GetService<IBotTelemetryClient>(), settings.LogPersonalData));

            // Configure bot services
            services.AddSingleton<BotServices>();

            // Configure storage
            // Uncomment the following line for local development without Cosmos Db
            // services.AddSingleton<IStorage, MemoryStorage>();
            services.AddSingleton<IStorage>(new CosmosDbPartitionedStorage(settings.CosmosDb));
            services.AddSingleton<UserState>();
            services.AddSingleton<ConversationState>();

            // Configure localized responses
            var localizedTemplates = new Dictionary<string, string>();
            var templateFile = "AllResponses";
            var supportedLocales = new List<string>() { "en-us", "de-de", "es-es", "fr-fr", "it-it", "zh-cn" };

            foreach (var locale in supportedLocales)
            {
                // LG template for en-us does not include locale in file extension.
                var localeTemplateFile = locale.Equals("en-us")
                    ? Path.Combine(".", "Responses", $"{templateFile}.lg")
                    : Path.Combine(".", "Responses", $"{templateFile}.{locale}.lg");

                localizedTemplates.Add(locale, localeTemplateFile);
            }

            services.AddSingleton(new LocaleTemplateManager(localizedTemplates, settings.DefaultLocale ?? "en-us"));

            // Register the Bot Framework Adapter with error handling enabled.
            // Note: some classes use the base BotAdapter so we add an extra registration that pulls the same instance.
            services.AddSingleton<BotFrameworkHttpAdapter, DefaultAdapter>();
            services.AddSingleton<BotAdapter>(sp => sp.GetService<BotFrameworkHttpAdapter>());

            // Register the skills conversation ID factory, the client and the request handler.
            services.AddSingleton<SkillConversationIdFactoryBase, SkillConversationIdFactory>();
            services.AddHttpClient<SkillHttpClient>();
            services.AddSingleton<ChannelServiceHandler, TokenExchangeSkillHandler>();

            // Register dialogs
            services.AddTransient<MainDialog>();
            services.AddTransient<SwitchSkillDialog>();
            services.AddTransient<OnboardingDialog>();

            // Register the SkillDialogs (remote skills).
            var botId = Configuration.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey)?.Value;
            if (string.IsNullOrWhiteSpace(botId))
            {
                throw new ArgumentException($"{MicrosoftAppCredentials.MicrosoftAppIdKey} is not in configuration");
            }

            foreach (var skill in skillsConfig.Skills.Values)
            {
                services.AddSingleton(sp =>
                {
                    var skillDialogOptions = new SkillDialogOptions
                    {
                        BotId = botId,
                        ConversationIdFactory = sp.GetService<SkillConversationIdFactoryBase>(),
                        SkillClient = sp.GetService<SkillHttpClient>(),
                        SkillHostEndpoint = skillsConfig.SkillHostEndpoint,
                        Skill = skill,
                        ConversationState = sp.GetService<ConversationState>()
                    };

                    return new SkillDialog(skillDialogOptions, skill.Id);
                });
            }

            // Configure TokenExchangeConfig for SSO
            if (settings.TokenExchangeConfig != null)
            {
                services.AddSingleton<ITokenExchangeConfig>(settings.TokenExchangeConfig);
            }

            // Configure bot
            services.AddTransient<IBot, DefaultActivityHandler<MainDialog>>();
        }