/// <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 <EchoWithCounterBot>(options => { var blobStore = new AzureBlobTranscriptStore("DefaultEndpointsProtocol=https;AccountName=sq7ofgblobs;AccountKey=2k0LVUrttdcPB50R3DNIgZrB2ff1yapC6Iv0r/SeCKFW4D+bL2ezwy8zO0lCw/Adw2ysPSdsu13OZ07RtXufFw==;EndpointSuffix=core.windows.net", "bot-storage"); var transcriptMiddleware = new TranscriptLoggerMiddleware(blobStore); options.Middleware.Add(transcriptMiddleware); // Creates a logger for the application to use. ILogger logger = _loggerFactory.CreateLogger <EchoWithCounterBot>(); //var secretKey = Configuration.GetSection("botFileSecret")?.Value; //var botFilePath = Configuration.GetSection("botFilePath")?.Value; var secretKey = "s0/1svAFPxOxUcTfsyoILPUcWLfJlACnsGlkzAotEGw="; var botFilePath = "./customerassistant.bot"; if (!File.Exists(botFilePath)) { throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}"); } // 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 { var msg = @"Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment. - You can find the botFilePath and botFileSecret in the Azure App Service application settings. - If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret. - See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration. "; logger.LogError(msg); throw new InvalidOperationException(msg); } services.AddSingleton(sp => botConfig); // Retrieve current endpoint. var environment = _isProduction ? "production" : "development"; var service = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment); if (service == null && _isProduction) { // Attempt to load development environment service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == "development").FirstOrDefault(); logger.LogWarning("Attempting to load development endpoint in production environment."); } if (!(service is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); options.ChannelProvider = new ConfigurationChannelProvider(Configuration); // Catches any errors that occur during a conversation turn and logs them. options.OnTurnError = async(context, exception) => { logger.LogError($"Exception caught : {exception}"); Console.WriteLine($"Exception: {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 = "botstate"; // 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 ConversationState(dataStore); var userState = new UserState(dataStore); options.State.Add(conversationState); services.AddSingleton <StateBotAccessors>(sp => { // Create the custom state accessor. return(new StateBotAccessors(conversationState, userState) { ConversationDataAccessor = conversationState.CreateProperty <ConversationData>(StateBotAccessors.ConversationDataName), UserProfileAccessor = userState.CreateProperty <UserData>(StateBotAccessors.UserProfileName), }); }); }); // Create and register state accessors. // Accessors created here are passed into the IBot-derived class on every turn. services.AddSingleton <EchoBotAccessors>(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 <ConversationState>().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 EchoBotAccessors(conversationState) { CounterState = conversationState.CreateProperty <CounterState>(EchoBotAccessors.CounterStateName), }; return(accessors); }); }
/** * Constructor. * * @param {BotConfiguration} bot configuration * @param {ConversationState} conversationState * @param {StatePropertyAccessor} accessor for user profile property * @param {StatePropertyAccessor} accessor for on turn property * @param {StatePropertyAccessor} accessor for reservation property */ public WhoAreYouDialog( BotServices botServices, ConversationState conversationState, IStatePropertyAccessor<UserProfile> userProfileAccessor, IStatePropertyAccessor<OnTurnProperty> onTurnAccessor, IStatePropertyAccessor<ReservationProperty> reservationAccessor) : base(Name) { if (botServices == null) { throw new ArgumentNullException(nameof(botServices)); } if (conversationState == null) { throw new ArgumentNullException(nameof(conversationState)); } UserProfileAccessor = userProfileAccessor ?? throw new ArgumentNullException(nameof(userProfileAccessor)); // Keep accessors for the steps to consume OnTurnAccessor = onTurnAccessor ?? throw new ArgumentNullException(nameof(onTurnAccessor)); // Add dialogs var waterfallSteps = new WaterfallStep[] { AskForUserNameAsync, GreetUserAsync, }; AddDialog(new WaterfallDialog( dialogStart, waterfallSteps)); var turnCounterAccessor = conversationState.CreateProperty<CounterState>("turnCounter"); // Add get user name prompt. AddDialog(new GetUserNamePrompt( askUserNamePrompt, botServices, userProfileAccessor, conversationState, onTurnAccessor, turnCounterAccessor, async (promptContext, cancellationToken) => { var userProfile = await userProfileAccessor.GetAsync(promptContext.Context); var counter = await turnCounterAccessor.GetAsync(promptContext.Context); // Prompt validator // Examine if we have a user name and validate it. if (userProfile != null && userProfile.UserName != null) { // We can only accept user names that up to two words. if (userProfile.UserName.Split(" ").Length > 2) { await promptContext.Context.SendActivityAsync("Sorry, I can only accept two words for a name."); await promptContext.Context.SendActivityAsync("You can always say 'My name is <your name>' to introduce yourself to me."); await userProfileAccessor.SetAsync(promptContext.Context, new UserProfile("Human")); // Set updated turn counter await turnCounterAccessor.SetAsync(promptContext.Context, counter); return false; } else { // Capitalize user name userProfile.UserName = char.ToUpper(userProfile.UserName[0]) + userProfile.UserName.Substring(1); // Create user profile and set it to state. await userProfileAccessor.SetAsync(promptContext.Context, userProfile); return true; } } return false; })); // This dialog is interruptable, add interruptionDispatcherDialog AddDialog(new InterruptionDispatcher(onTurnAccessor, conversationState, userProfileAccessor, botServices)); // When user decides to abandon this dialog, we need to confirm user action - add confirmation prompt AddDialog(new ConfirmPrompt(confirmCancelPrompt)); }
public StateManagementBot(ConversationState conversationState, UserState userState) { _conversationState = conversationState; _userState = userState; }
public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null) : base(configuration, logger) { OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError($"Exception caught : {exception.Message}"); // Send a catch-all apology to the user. var errorMessage = MessageFactory.Text(ErrorMsgText, ErrorMsgText, InputHints.ExpectingInput); await turnContext.SendActivityAsync(errorMessage); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError($"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } }; }
public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null) : base(configuration, logger) { OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); // Send a message to the user await turnContext.SendActivityAsync("The bot encounted an error or bug."); await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code."); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } // Send a trace activity, which will be displayed in the Bot Framework Emulator await SendTraceActivityAsync(turnContext, exception); }; }
public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null) : base(configuration: configuration, new ConfigurationCredentialProvider(configuration), logger: logger, authConfig: new AuthenticationConfiguration { ClaimsValidator = new AllowedCallersClaimsValidator(new List <string> { "*" }) }) { OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. // NOTE: In production environment, you should consider logging this to // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how // to add telemetry capture to your bot. logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); // Send a message to the user await turnContext.SendActivityAsync("The bot encountered an error or bug."); await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code."); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } // Send a trace activity, which will be displayed in the Bot Framework Emulator await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError"); }; }
public WeatherCardBot(ConversationState conversationState, UserState userState, MainDialog dialog, ILogger <DialogBot <MainDialog> > logger) : base(conversationState, userState, dialog, logger) { }
/// <summary>/ /// This method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services">Specifies the contract for a <see cref="IServiceCollection"/> of service descriptors.</param> /// <seealso cref="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1"/> public void ConfigureServices(IServiceCollection services) { // Add botConfiguration singleton // See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration. var secretKey = Configuration.GetSection("botFileSecret")?.Value; var botFilePath = Configuration.GetSection("botFilePath")?.Value; var botConfig = BotConfiguration.Load(botFilePath ?? @".\CafeBot.bot", secretKey); services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration file could not be loaded. botFilePath: {botFilePath}")); // Add BotServices singleton services.AddSingleton(sp => new BotServices(botConfig)); // 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/ // Un-comment 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); services.AddSingleton(dataStore); var userState = new UserState(dataStore); var conversationState = new ConversationState(dataStore); services.AddSingleton(userState); services.AddSingleton(conversationState); // The BotStateSet enables read() and write() in parallel on multiple BotState instances. services.AddSingleton(new BotStateSet(userState, conversationState)); // Add the bot with options services.AddBot <CafeBot>(options => { // Load the connected services from .bot file. 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 SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); // Catches any errors that occur during a conversation turn and logs them to currently // configured ILogger. ILogger logger = _loggerFactory.CreateLogger <CafeBot>(); options.OnTurnError = async(context, exception) => { logger.LogError($"Exception caught : {exception}"); await context.SendActivityAsync("Sorry, it looks like something went wrong."); }; // Automatically save state at the end of a turn. options.Middleware .Add(new AutoSaveStateMiddleware(userState, conversationState)); }); }
/// <summary> /// Initializes a new instance of the <see cref="WelcomeUserStateAccessors"/> class. /// Contains the <see cref="UserState"/> and associated <see cref="IStatePropertyAccessor{T}"/>. /// </summary> /// <param name="userState">The state object that stores the counter.</param> public WelcomeUserStateAccessors(UserState userState, ConversationState conversationState) { UserState = userState ?? throw new ArgumentNullException(nameof(userState)); }
public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, TranslationMiddleware translationMiddleware, ConversationState conversationState = null) : base(configuration, logger) { if (translationMiddleware == null) { throw new NullReferenceException(nameof(translationMiddleware)); } // Add translation middleware to the adapter's middleware pipeline Use(translationMiddleware); OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); // Send a message to the user //await SendWithoutMiddleware("The bot encounted an error or bug."); //await SendWithoutMiddleware("To continue to run this bot, please fix the bot source code."); await SendWithoutMiddleware(turnContext, configuration["InternalErrorResponse"]); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } // Send a trace activity, which will be displayed in the Bot Framework Emulator await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError"); }; }
public void ConfigureServices(IServiceCollection services) { var secretKey = Configuration.GetSection("botFileSecret")?.Value; var botFilePath = Configuration.GetSection("botFilePath")?.Value; if (!File.Exists(botFilePath)) { throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}"); } // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection. BotConfiguration botConfig = null; try { botConfig = BotConfiguration.Load(botFilePath, secretKey); } catch { var msg = @"Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment. - You can find the botFilePath and botFileSecret in the Azure App Service application settings. - If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret. - See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration. "; throw new InvalidOperationException(msg); } services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration file could not be loaded. botFilePath: {botFilePath}")); // Add BotServices singleton. // Create the connected services from .bot file. services.AddSingleton(sp => new BotServices(botConfig)); // Retrieve current endpoint. var environment = _isProduction ? "production" : "development"; var service = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment); if (service == null && _isProduction) { // Attempt to load development environment service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == "development").FirstOrDefault(); } if (!(service is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } // Memory Storage is for local bot debugging only. When the bot // is restarted, everything stored in memory will be gone. IStorage dataStore = new MemoryStorage(); // Create and add conversation state. var conversationState = new ConversationState(dataStore); services.AddSingleton(conversationState); var userState = new UserState(dataStore); services.AddSingleton(userState); services.AddBot <BasicBot>(options => { options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); options.ChannelProvider = new ConfigurationChannelProvider(Configuration); // Catches any errors that occur during a conversation turn and logs them to currently // configured ILogger. ILogger logger = _loggerFactory.CreateLogger <BasicBot>(); options.OnTurnError = async(context, exception) => { logger.LogError($"Exception caught : {exception}"); await context.SendActivityAsync("Sorry, it looks like something went wrong."); }; }); }
public AdapterWithErrorHandler(IConfiguration configuration, IHttpClientFactory httpClientFactory, ILogger <IBotFrameworkHttpAdapter> logger, ConversationState conversationState) : base(configuration, httpClientFactory, logger) { OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. // NOTE: In production environment, you should consider logging this to // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how // to add telemetry capture to your bot. logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); // Send a message to the user var errorMessageText = "The bot encountered an error or bug."; var errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.IgnoringInput); await turnContext.SendActivityAsync(errorMessage); errorMessageText = "To continue to run this bot, please fix the bot source code."; errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput); await turnContext.SendActivityAsync(errorMessage); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } // Send a trace activity, which will be displayed in the Bot Framework Emulator await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError"); }; }
/// <summary> /// Initializes a new instance of the <see cref="CustomPromptBotAccessors"/> class. /// Contains the state management and associated accessor objects. /// </summary> /// <param name="conversationState">The state object that stores the conversation state.</param> /// <param name="userState">The state object that stores the user state.</param> public CustomPromptBotAccessors(ConversationState conversationState, UserState userState) { ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState)); UserState = userState ?? throw new ArgumentNullException(nameof(userState)); }
/// <summary> /// Initializes a new instance of the <see cref="DialogInterruptionsBotAccessors"/> class. /// Contains the <see cref="ConversationState"/> and associated <see cref="IStatePropertyAccessor{T}"/>. /// </summary> /// <param name="conversationState">The state object that stores the dialog state.</param> /// <param name="userState">The state object that stores the user state.</param> public DialogInterruptionsBotAccessors(ConversationState conversationState, UserState userState) { ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState)); UserState = userState ?? throw new ArgumentNullException(nameof(userState)); }
/// <summary> /// This method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services">Specifies the contract for a <see cref="IServiceCollection"/> 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 <CardsBot>(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 ?? @".\BotConfiguration.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.Where(s => s.Type == "endpoint" && s.Name == environment).FirstOrDefault(); if (!(service is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); // Creates a logger for the application to use. ILogger logger = _loggerFactory.CreateLogger <CardsBot>(); // 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 ConversationState(dataStore); options.State.Add(conversationState); }); // Create and register state accessors. // Accessors created here are passed into the IBot-derived class on every turn. services.AddSingleton <CardsBotAccessors>(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 <ConversationState>().FirstOrDefault(); if (conversationState == null) { throw new InvalidOperationException( "ConversationState must be defined and added before adding conversation-scoped state accessors."); } // Create custom state property accessors. // State property accessors enable components to read and write individual properties, // without having to pass the entire state object. var accessors = new CardsBotAccessors(conversationState) { ConversationDialogState = conversationState.CreateProperty <DialogState>(CardsBotAccessors.DialogStateName), }; return(accessors); }); }
public AuthBot(ConversationState conversationState, UserState userState, T dialog, ILogger <DialogBot <T> > logger) : base(conversationState, userState, dialog, logger) { }
public AdapterWithErrorHandler(ICredentialProvider credentialProvider, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null) : base(credentialProvider) { // combine path for cross platform support string[] paths = { ".", "Resources", "AdapterWithErrorHandler.lg" }; string fullPath = Path.Combine(paths); _lgEngine = new TemplateEngine().AddFile(fullPath); OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError($"Exception caught : {exception.Message}"); // Send a catch-all apology to the user. await turnContext.SendActivityAsync(ActivityFactory.CreateActivity(_lgEngine.EvaluateTemplate("SomethingWentWrong", exception).ToString())); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError($"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } }; }
/// <summary> /// This method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services">Specifies the contract for a <see cref="IServiceCollection"/> of service descriptors.</param> /// <seealso cref="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1"/> public void ConfigureServices(IServiceCollection services) { var secretKey = Configuration.GetSection("botFileSecret")?.Value; var botFilePath = Configuration.GetSection("botFilePath")?.Value; if (!File.Exists(botFilePath)) { throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}"); } // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection. var botConfig = BotConfiguration.Load(botFilePath ?? @".\qnamaker.bot", secretKey); // Initialize Bot Connected Services clients. var connectedServices = new BotServices(botConfig); services.AddSingleton(sp => connectedServices); services.AddSingleton(sp => botConfig); services.AddBot <QnABot>(options => { services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration 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 SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); // Creates a logger for the application to use. ILogger logger = _loggerFactory.CreateLogger <QnABot>(); // 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 ConversationState(dataStore); options.State.Add(conversationState); }); }
/// <summary> /// This method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services">Specifies the contract for a <see cref="IServiceCollection"/> of service descriptors.</param> public void ConfigureServices(IServiceCollection services) { //var secretKey = Configuration.GetSection("botFileSecret")?.Value; //var botFilePath = Configuration.GetSection("botFilePath")?.Value; var secretKey = "CNjqDnw4n9d8zTXmmrywJybwHQ+K1Ke0AmmTWTS5854="; var botFilePath = "./sq7ofg.bot"; if (!File.Exists(botFilePath)) { throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}"); } // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection. BotConfiguration botConfig = null; try { botConfig = BotConfiguration.Load(botFilePath, secretKey); } catch { var msg = @"Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment. - You can find the botFilePath and botFileSecret in the Azure App Service application settings. - If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret. - See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration. "; throw new InvalidOperationException(msg); } services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration file could not be loaded. botFilePath: {botFilePath}")); // Add BotServices singleton. // Create the connected services from .bot file. services.AddSingleton(sp => new BotServices(botConfig)); // Retrieve current endpoint. var environment = _isProduction ? "production" : "development"; var service = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment); if (service == null && _isProduction) { // Attempt to load development environment service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == "development").FirstOrDefault(); } if (!(service is EndpointService endpointService)) { throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); } // Memory Storage 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/ // Un-comment 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 = "botstate"; // var storageContainer = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container; // IStorage dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer); // Create and add conversation state. var conversationState = new ConversationState(dataStore); services.AddSingleton(conversationState); var userState = new UserState(dataStore); services.AddSingleton(userState); services.AddBot <BasicBot>(options => { options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); options.ChannelProvider = new ConfigurationChannelProvider(Configuration); // Catches any errors that occur during a conversation turn and logs them to currently // configured ILogger. ILogger logger = _loggerFactory.CreateLogger <BasicBot>(); options.OnTurnError = async(context, exception) => { logger.LogError($"Exception caught : {exception}"); await context.SendActivityAsync("Sorry, it looks like something went wrong."); }; }); }
public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null) : base(configuration, logger) { OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError($"Exception caught : {exception.Message}"); // Send a catch-all apology to the user. await turnContext.SendActivityAsync("Sorry, it looks like something went wrong."); await turnContext.SendActivityAsync("To run this sample make sure you have the LUIS and QnA models deployed."); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError($"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } }; }
/// <summary> /// Initializes a new instance of the <see cref="BotAccessors"/> class. /// Contains the <see cref="ConversationState"/> and associated <see cref="IStatePropertyAccessor{T}"/>. /// </summary> /// <param name="conversationState">The state object that stores the dialog state.</param> public BotAccessors(ConversationState conversationState) { ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState)); }
public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null) : base(configuration, logger) { OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); // Send a message to the user var errorMessageText = "Oops! Something went wrong!"; var errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput); await turnContext.SendActivityAsync(errorMessage); errorMessageText = "Could you please refresh the page and start over."; errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput); await turnContext.SendActivityAsync(errorMessage); if (conversationState != null) { try { // Delete the conversationState for the current conversation to prevent the // bot from getting stuck in a error-loop caused by being in a bad state. // ConversationState should be thought of as similar to "cookie-state" in a Web pages. await conversationState.DeleteAsync(turnContext); } catch (Exception e) { logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}"); } } // Send a trace activity, which will be displayed in the Bot Framework Emulator await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError"); }; }
public BookTableDialog(BotServices services, IStatePropertyAccessor <ReservationProperty> reservationsAccessor, IStatePropertyAccessor <OnTurnProperty> onTurnAccessor, IStatePropertyAccessor <UserProfile> userProfileAccessor, ConversationState conversationState) : base(Name) { _services = services ?? throw new ArgumentNullException(nameof(services)); ReservationsAccessor = reservationsAccessor ?? throw new ArgumentNullException(nameof(reservationsAccessor)); OnTurnAccessor = onTurnAccessor ?? throw new ArgumentNullException(nameof(onTurnAccessor)); UserProfileAccessor = userProfileAccessor ?? throw new ArgumentNullException(nameof(userProfileAccessor)); // Create accessors for child dialogs GetLocDialogAccessor = conversationState.CreateProperty <DialogState>(GetLocationDialogState); ConfirmDialogAccessor = conversationState.CreateProperty <DialogState>(ConfirmDialogState); // Add dialogs // Water fall book table dialog var waterfallSteps = new WaterfallStep[] { GetAllRequiredPropertiesAsync, BookTableAsync, }; AddDialog(new WaterfallDialog(BookTableWaterfall, waterfallSteps)); // Get location, date, time & party size prompt. AddDialog(new GetLocationDateTimePartySizePrompt( GetLocationDateTimePartySizePrompt, services, reservationsAccessor, onTurnAccessor, userProfileAccessor, async(promptValidatorContext, cancellationToken) => { // Validation and prompting logic. // Get reservation property. var newReservation = await reservationsAccessor.GetAsync(promptValidatorContext.Context, () => new ReservationProperty()); // If we have a valid reservation, end this prompt. // Otherwise, get LG based on what's available in reservation property if (newReservation.HaveCompleteReservation()) { if (!newReservation.ReservationConfirmed) { if (newReservation.NeedsChange == true) { await promptValidatorContext.Context.SendActivityAsync("What would you like to change ?"); } else { // Greet user with name if we have the user profile set. var userProfile = await userProfileAccessor.GetAsync(promptValidatorContext.Context, () => null); if (userProfile != null && !string.IsNullOrWhiteSpace(userProfile.UserName)) { await promptValidatorContext.Context.SendActivityAsync($"Alright {userProfile.UserName} I have a table for {newReservation.ConfirmationReadOut()}"); } else { await promptValidatorContext.Context.SendActivityAsync($"Ok. I have a table for {newReservation.ConfirmationReadOut()}"); } await promptValidatorContext.Context.SendActivityAsync(MessageFactory.SuggestedActions(new List <string> { "Yes", "No" }, "Should I go ahead and book the table?")); } } else { // Have complete reservation. return(true); } } else { // Readout what has been understood already. var groundedPropertiesReadout = newReservation.GetGroundedPropertiesReadOut(); if (string.IsNullOrWhiteSpace(groundedPropertiesReadout)) { await promptValidatorContext.Context.SendActivityAsync(groundedPropertiesReadout); } } // Ask user for missing information await promptValidatorContext.Context.SendActivityAsync(newReservation.GetMissingPropertyReadOut()); return(false); })); // This dialog is interruptable. So add interruptionDispatcherDialog. AddDialog(new InterruptionDispatcher(onTurnAccessor, conversationState, userProfileAccessor, services)); // When user decides to abandon this dialog, we need to confirm user action. Add confirmation prompt. AddDialog(new ConfirmPrompt(ConfirmCancelPrompt)); }