/// <summary> /// Registers the specified configuration. /// </summary> /// <param name="config">The configuration.</param> public static void Register(HttpConfiguration config) { var builder = new ContainerBuilder(); // Register your Web API controllers. builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); config.MapBotFramework(botConfig => { // Load Connected Services from .bot file string path = HostingEnvironment.MapPath(@"~/BotConfiguration.bot"); var botConfigurationFile = BotConfiguration.Load(path); var endpointService = (EndpointService)botConfigurationFile.Services.First(s => s.Type == "endpoint"); botConfig .UseMicrosoftApplicationIdentity(endpointService?.AppId, endpointService?.AppPassword); // 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(); // Create Conversation State object. // The Conversation State object is where we persist anything at the conversation-scope. TeamSpecificConversationState conversationState = new TeamSpecificConversationState(dataStore); botConfig.BotFrameworkOptions.State.Add(conversationState); // Drop all activites not received from Microsoft Teams channel. botConfig.BotFrameworkOptions.Middleware.Add(new DropNonTeamsActivitiesMiddleware()); // --> Add Teams Middleware. botConfig.BotFrameworkOptions.Middleware.Add( new TeamsMiddleware( new SimpleCredentialProvider(endpointService?.AppId, endpointService?.AppPassword))); // Automatically drop all non Team messages. botConfig.BotFrameworkOptions.Middleware.Add(new DropChatActivitiesMiddleware()); // Create the custom state accessor. // State accessors enable other components to read and write individual properties of state. var accessors = new AuditLogAccessor(conversationState) { AuditLog = conversationState.CreateProperty <TeamOperationHistory>(AuditLogAccessor.AuditLogName), }; builder.Register <AuditLogAccessor>((component) => accessors); }); builder.RegisterType <TeamsActivityProcessor>().As <IActivityProcessor>(); builder.RegisterType <TeamsConversationUpdateActivityHandler>().As <ITeamsConversationUpdateActivityHandler>(); builder.RegisterType <MessageActivityHandler>().As <IMessageActivityHandler>(); builder.RegisterType <AuditBot>().As <IBot>().InstancePerRequest(); // Set the dependency resolver to be Autofac. IContainer container = builder.Build(); config.DependencyResolver = new AutofacWebApiDependencyResolver(container); }
/// <summary> /// Configures the services. This method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services">The services.</param> public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddBot <EchoBot>(options => { IStorage dataStore = new MemoryStorage(); // --> Adding conversation state handler which understands a team as single conversation. options.State.Add(new TeamSpecificConversationState(dataStore)); // Drop all activities not coming from Microsoft Teams. options.Middleware.Add(new DropNonTeamsActivitiesMiddleware()); // --> Add Teams Middleware. options.Middleware.Add( new TeamsMiddleware( new ConfigurationCredentialProvider(this.Configuration))); options.CredentialProvider = new ConfigurationCredentialProvider(this.Configuration); }); services.AddSingleton(sp => { BotFrameworkOptions options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value; if (options == null) { throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the State Accessors"); } TeamSpecificConversationState conversationState = options.State.OfType <TeamSpecificConversationState>().FirstOrDefault(); if (conversationState == null) { throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors."); } // Create the custom state accessor. // State accessors enable other components to read and write individual properties of state. var accessors = new EchoStateAccessor(conversationState) { CounterState = conversationState.CreateProperty <EchoState>(EchoStateAccessor.CounterStateName), }; return(accessors); }); }
/// <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 <EchoBot>(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 ?? @".\Echo.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"; 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}'."); } options.CredentialProvider = new ConfigurationCredentialProvider(this.Configuration); // Creates a logger for the application to use. ILogger logger = _loggerFactory.CreateLogger <EchoBot>(); // 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 = "<STORAGE-NAME-OR-ID-FROM-BOT-FILE>"; // var blobConfig = botConfig.FindServiceByNameOrId(StorageConfigurationId); // if (!(blobConfig is BlobStorageService blobStorageConfig)) // { // throw new InvalidOperationException($"The .bot file does not contain an blob storage with name '{StorageConfigurationId}'."); // } // // Default container name. // const string DefaultBotContainer = "<DEFAULT-CONTAINER>"; // var storageContainer = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container; // IStorage dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer); // Create Conversation State object. // The Conversation State object is where we persist anything at the conversation-scope. var conversationState = new TeamSpecificConversationState(dataStore); options.Middleware.Add(new DropNonTeamsActivitiesMiddleware()); options.Middleware.Add(new TeamsMiddleware( new ConfigurationCredentialProvider(this.Configuration))); options.State.Add(conversationState); }); // Create and register state accessors. // Accessors created here are passed into the IBot-derived class on every turn. services.AddSingleton <EchoAccessors>(sp => { var options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value; if (options == null) { throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the state accessors"); } var conversationState = options.State.OfType <TeamSpecificConversationState>().FirstOrDefault(); if (conversationState == null) { throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors."); } // Create the custom state accessor. // State accessors enable other components to read and write individual properties of state. var accessors = new EchoAccessors(conversationState) { CounterState = conversationState.CreateProperty <CounterState>(EchoAccessors.CounterStateName), }; return(accessors); }); }
/// <summary> /// Initializes a new instance of the <see cref="EchoStateAccessor"/> class. /// Contains the <see cref="ConversationState"/> and associated <see cref="IStatePropertyAccessor{T}"/>. /// </summary> /// <param name="conversationState">The state object that stores the counter.</param> public EchoStateAccessor(TeamSpecificConversationState conversationState) { this.ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState)); }
/// <summary> /// Configures the services. This method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services">The services.</param> public void ConfigureServices(IServiceCollection services) { string secretKey = this.Configuration.GetSection("botFileSecret")?.Value; string botFilePath = this.Configuration.GetSection("botFilePath")?.Value; // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection. BotConfiguration botConfig = null; try { botConfig = BotConfiguration.Load(botFilePath ?? @".\BotConfiguration.bot", secretKey); } catch { string msg = "Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.\n" + " - The botFileSecret is available under appsettings for your Azure Bot Service bot.\n" + " - If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret.\n" + " - See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.\n\n"; throw new InvalidOperationException(msg); } services.AddSingleton(sp => botConfig); // Retrieve current endpoint. string environment = this.isProduction ? "production" : "development"; ConnectedService botService = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == environment).FirstOrDefault(); if (!(botService is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } services.AddTransient <IActivityProcessor, TeamsActivityProcessor>(); services.AddTransient <ITeamsConversationUpdateActivityHandler, TeamsConversationUpdateActivityHandler>(); services.AddTransient <IMessageActivityHandler, MessageActivityHandler>(); services.AddBot <AuditBot>(options => { IStorage dataStore = new MemoryStorage(); // --> Adding conversation state handler which understands a team as single conversation. options.State.Add(new TeamSpecificConversationState(dataStore)); options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); // Drop all activities not coming from Microsoft Teams. options.Middleware.Add(new DropNonTeamsActivitiesMiddleware()); // --> Add Teams Middleware. options.Middleware.Add( new TeamsMiddleware( options.CredentialProvider)); // Drop all non team messages. options.Middleware.Add(new DropChatActivitiesMiddleware()); }); services.AddSingleton(sp => { BotFrameworkOptions options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value; if (options == null) { throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the State Accessors"); } TeamSpecificConversationState conversationState = options.State.OfType <TeamSpecificConversationState>().FirstOrDefault(); if (conversationState == null) { throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors."); } // Create the custom state accessor. // State accessors enable other components to read and write individual properties of state. var accessors = new AuditLogAccessor(conversationState) { AuditLog = conversationState.CreateProperty <TeamOperationHistory>(AuditLogAccessor.AuditLogName), }; return(accessors); }); }
// 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 storage we'll be using for User and Conversation state. (Memory is great for testing purposes.) services.AddSingleton <IStorage, MemoryStorage>(); // Create the User state. (Used in this bot's Dialog implementation.) services.AddSingleton <UserState>(); // Create the Conversation state. (Used by the Dialog system itself.) services.AddSingleton <ConversationState>(); services.AddSingleton <MainDialog>(); // Add the HttpClientFactory to be used for the QnAMaker calls. services.AddHttpClient(); // 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, DialogAndWelcomeBot <MainDialog> >(); services.AddBot <DialogAndWelcomeBot <MainDialog> >(options => { options.CredentialProvider = new ConfigurationCredentialProvider(this.Configuration); // 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 = "<STORAGE-NAME-OR-ID-FROM-BOT-FILE>"; // var blobConfig = botConfig.FindServiceByNameOrId(StorageConfigurationId); // if (!(blobConfig is BlobStorageService blobStorageConfig)) // { // throw new InvalidOperationException($"The .bot file does not contain an blob storage with name '{StorageConfigurationId}'."); // } // // Default container name. // const string DefaultBotContainer = "<DEFAULT-CONTAINER>"; // var storageContainer = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container; // IStorage dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer); // Create Conversation State object. // The Conversation State object is where we persist anything at the conversation-scope. var conversationState = new TeamSpecificConversationState(dataStore); options.Middleware.Add(new DropNonTeamsActivitiesMiddleware()); options.Middleware.Add(new TeamsMiddleware( new ConfigurationCredentialProvider(this.Configuration))); options.State.Add(conversationState); }); // Create and register state accessors. // Accessors created here are passed into the IBot-derived class on every turn. services.AddSingleton <EchoAccessors>(sp => { var options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value; if (options == null) { throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the state accessors"); } var conversationState = options.State.OfType <TeamSpecificConversationState>().FirstOrDefault(); if (conversationState == null) { throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors."); } // Create the custom state accessor. // State accessors enable other components to read and write individual properties of state. var accessors = new EchoAccessors(conversationState) { CounterState = conversationState.CreateProperty <CounterState>(EchoAccessors.CounterStateName), }; return(accessors); }); }