Beispiel #1
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services">The <see cref="IServiceCollection"/> specifies the contract for a collection of service descriptors.</param>
        /// <seealso cref="IStatePropertyAccessor{T}"/>
        /// <seealso cref="https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection"/>
        /// <seealso cref="https://docs.microsoft.com/en-us/azure/bot-service/bot-service-manage-channels?view=azure-bot-service-4.0"/>
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddBot <SyntinelBot>(options =>
            {
                var secretKey   = Configuration.GetSection("BotFileSecret")?.Value;
                var botFilePath = Configuration.GetSection("BotFilePath")?.Value;

                // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
                var botConfig = BotConfiguration.Load(botFilePath ?? @".\syntinel.bot", secretKey);
                services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded. ({botConfig})"));

                // Retrieve current endpoint.
                var environment = _isProduction ? "production" : "development";

                // The default value for reference and nullable types is null.
                var service = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment);
                if (!(service is EndpointService endpointService))
                {
                    throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
                }

                // Sets bot credentials
                options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);

                // Catches any errors that occur during a conversation turn and logs them.
                options.OnTurnError = async(context, exception) =>
                {
                    _logger.LogError($"Exception caught : {exception}");
                    await context.SendActivityAsync("Sorry, it looks like something went wrong.");
                };

                // The Memory Storage used here is for local bot debugging only. When the bot
                // is restarted, everything stored in memory will be gone.
                // IStorage dataStore = new MemoryStorage();

                // For production bots use the Azure Blob or
                // Azure CosmosDB storage providers. For the Azure
                // based storage providers, add the Microsoft.Bot.Builder.Azure
                // Nuget package to your solution. That package is found at:
                // https://www.nuget.org/packages/Microsoft.Bot.Builder.Azure/
                // Uncomment the following lines to use Azure Blob Storage
                // //Storage configuration name or ID from the .bot file.
                const string StorageConfigurationId = "SyntinelBot";
                var cosmoConfig = botConfig.FindServiceByNameOrId(StorageConfigurationId);
                if (!(cosmoConfig is CosmosDbService cosmoStorageConfig))
                {
                    throw new InvalidOperationException($"The .bot file does not contain a cosmo storage with name '{StorageConfigurationId}'.");
                }

                IStorage dataStore = new CosmosDbStorage(new CosmosDbStorageOptions
                {
                    CollectionId     = cosmoStorageConfig.Collection,
                    CosmosDBEndpoint = new Uri(cosmoStorageConfig.Endpoint),
                    DatabaseId       = cosmoStorageConfig.Database,
                    AuthKey          = cosmoStorageConfig.Key,
                });

                _botStore = dataStore;

                // Create Conversation State object.
                // The Conversation State object is where we persist anything at the conversation-scope.
                _conversationState = new ConversationState(dataStore);
                _userState         = new UserState(dataStore);
                _serviceState      = new ServiceState(dataStore);
            });

            // https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-tutorial-persist-user-inputs?view=azure-bot-service-4.0&tabs=csharp
            // Create and register state accesssors.
            // Acessors created here are passed into the IBot-derived class on every turn.
            services.AddSingleton <BotAccessors>(sp =>
            {
                if (_conversationState == null)
                {
                    throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors.");
                }

                if (_userState == null)
                {
                    throw new InvalidOperationException("UserState must be defined and added before adding user-scoped state accessors.");
                }

                if (_serviceState == null)
                {
                    throw new InvalidOperationException("ServiceState must be defined and added before adding service-scoped state accessors.");
                }

                // Create the custom state accessor.
                // State accessors enable other components to read and write individual properties of state.
                var accessors = new BotAccessors(_conversationState, _userState, _serviceState)
                {
                    UserDataAccessor         = _userState.CreateProperty <UserData>(BotAccessors.UserDataName),
                    JobDataAccessor          = _serviceState.CreateProperty <Dictionary <string, Job> >(BotAccessors.JobDataName),
                    NotificationDataAccessor = _serviceState.CreateProperty <Dictionary <string, Notification> >(BotAccessors.NotificationDataName),
                    UserRegistryAccessor     = _serviceState.CreateProperty <RegisteredUsers>(BotAccessors.UserRegistryName),
                    ConversationDialogState  = _conversationState.CreateProperty <DialogState>(BotAccessors.DialogStateName),
                };

                return(accessors);
            });
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="BotAccessors"/> class.
        /// </summary>
        public BotAccessors(ConversationState conversationState, UserState userState, ServiceState serviceState)
        {
            ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState));

            UserState = userState ?? throw new ArgumentNullException(nameof(userState));

            ServiceState = serviceState ?? throw new ArgumentNullException(nameof(serviceState));
        }