public void TranslatorMiddleware_PropertyLocale() { var mockHttp = new MockHttpMessageHandler(); var tm = new TranslationMiddleware(new[] { "en" }, _translatorKey, httpClient: mockHttp.ToHttpClient()); Assert.AreEqual("en", tm.DefaultLocale); }
// This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddBot <MainBot>(options => { var secretKey = Configuration.GetSection("botFileSecret")?.Value; var botFilePath = Configuration.GetSection("botFilePath")?.Value; // Read BotConfiguration.bot and register it in IServiceCollection var botConfig = BotConfiguration.Load(botFilePath ?? @". \ BotConfiguration.bot", secretKey); services.AddSingleton(_ => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded. ({botConfig})")); // Optional. Logging and error handling var logger = LoggerFactory.CreateLogger <MainBot>(); options.OnTurnError = async(context, ex) => { logger.LogError($"Exception caught: {ex}"); await context.SendActivityAsync("Sorry, it looks like something went wrong."); }; // Obtain information on the endpoint of the current environment from BotConfiguration.bot. If not, it is an error. var environment = IsProduction ? "production" : "development"; var endpointService = botConfig .Services .FirstOrDefault(x => x.Type == "endpoint" && x.Name == environment) as EndpointService ?? throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'."); // Add Bot's authentication information options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword); // For development purposes only!In - memory store.The actual number seems to be Blob or something var storage = new MemoryStorage(); var conversationState = new ConversationState(storage); var userState = new UserState(storage); options.State.Add(conversationState); options.State.Add(userState); // Translation var translatorKey = "2faace0dff53457ca8538f7a635f73a8"; var translator = new MicrosoftTranslator(translatorKey); var translationMiddleware = new TranslationMiddleware(translator, userState.CreateProperty <string>("LanguagePreference")); options.Middleware.Add(translationMiddleware); }); // Add MainBotAccessor for state management services.AddSingleton(sp => { var options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value ?? throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the state accessors"); var conversationState = options.State.OfType <ConversationState>().FirstOrDefault() ?? throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors."); var userState = options.State.OfType <UserState>().FirstOrDefault() ?? throw new InvalidOperationException("UserState must be defined and added before adding user-scoped state accessors."); return(new MainBotAccessors(conversationState, userState)); }); }
public TranslationMiddlewareTest() { nextMiddlewareInPipelineDelegateMock = new Mock <RequestDelegate>(); tokenManagerMock = new Mock <IClientTokenManager>(); loggerMock = new Mock <ILogger <TranslationMiddleware> >(); errorLoggerMock = new Mock <IErrorLogger>(); memoryCache = new MemoryCache(new MemoryCacheOptions()); httpClientFactoryMock = new Mock <IHttpClientFactory>(); httpContextMock = new DefaultHttpContext(); httpContextMock.Response.Body = new MemoryStream(); httpContextMock.Request.Headers.Add("Accept-Language", "pt-BR"); tokenManagerMock.Setup(it => it.GetAccessTokenAsync()).ReturnsAsync(new Result <string> { Value = "some token" }); translateOptionsMock = Options.Create( new TranslationOptions { BaseUrl = "https://globalization.Myframeworkmonitor.com/", ResultTranslateRoute = "api/terms/results", Enabled = true, ApiTimeout = new System.TimeSpan(0, 5, 0), CacheTimeoutForSuccessResultTranslation = new System.TimeSpan(2, 0, 0), ThrowExceptionWhenErrorOcurrInTranslate = false }); globalizationOptionsMock = Options.Create( new GlobalizationOptions { DefaultRequestCulture = null, SupportedCultures = null, SupportedUICultures = null, UseQueryStringRequestCultureProvider = false }); resultTranslatedPtBr = new Result().Set(ResultCode.Ok, "Sucesso"); responseMock = new Mock <HttpResponseMessage>(); responseMock.Object.StatusCode = HttpStatusCode.OK; responseMock.Object.Content = new StringContent(JsonConvert.SerializeObject(resultTranslatedPtBr), Encoding.UTF8, "application/json"); handlerMock = new Mock <HttpMessageHandler>(MockBehavior.Strict); handlerMock .Protected() .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()) .ReturnsAsync(responseMock.Object) .Verifiable(); defaultHttpClient = new HttpClient(handlerMock.Object); httpClientFactoryMock.Setup(it => it.CreateClient(It.IsAny <string>())).Returns(defaultHttpClient); translationMiddleware = new TranslationMiddleware(nextMiddlewareInPipelineDelegateMock.Object, tokenManagerMock.Object, loggerMock.Object, errorLoggerMock.Object, translateOptionsMock, globalizationOptionsMock, memoryCache, httpClientFactoryMock.Object); }
public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, TranslationMiddleware translationMiddleware, TelemetryInitializerMiddleware telemetryInitializerMiddleware, ConversationState conversationState = null) : base(configuration, logger) { Use(telemetryInitializerMiddleware); Use(translationMiddleware); OnTurnError = async(turnContext, exception) => { logger.LogError($"Exception caught : {exception.Message}"); await turnContext.SendActivityAsync("Sorry, it looks like something went wrong."); }; }
public AdapterWithErrorHandler(IConfiguration configuration, IHttpClientFactory httpClientFactory, ILogger <IBotFrameworkHttpAdapter> logger, TranslationMiddleware translationMiddleware, ConversationState conversationState = null) : base(configuration, httpClientFactory, 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. // 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 SendWithoutMiddleware(turnContext, "The bot encountered an error or bug."); await SendWithoutMiddleware(turnContext, "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 AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, FeedbackMiddleware feedbackMiddleware, TranslationMiddleware translationMiddleware, ConversationState conversationState = null) : base(configuration, logger) { if (Util.IsSupportingMultiLingual) { if (translationMiddleware == null) { throw new NullReferenceException(nameof(translationMiddleware)); } // Add to the adapter's middleware pipeline Use(translationMiddleware); } if (Util.IsRequestingUserFeedback) { if (feedbackMiddleware == null) { throw new NullReferenceException(nameof(feedbackMiddleware)); } // Add to the adapter's middleware pipeline Use(feedbackMiddleware); } OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); 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"); }; }
/// <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) { services.AddBot <MultiLingualBot>(options => { 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 ?? @".\multilingual-bot.bot", secretKey); services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration file could not be loaded. botFilePath: {botFilePath}")); // 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 <MultiLingualBot>(); // Catches any errors that occur during a conversation turn and logs them. options.OnTurnError = async(turnContext, exception) => { logger.LogError($"Exception caught : {exception}"); // By-pass the middleware by sending the Activity directly on the Adapter. var activity = MessageFactory.Text("Sorry, it looks like something went wrong."); activity.ApplyConversationReference(turnContext.Activity.GetConversationReference()); await turnContext.Adapter.SendActivitiesAsync(turnContext, new[] { activity }, default(CancellationToken)); }; // 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 and add conversation state. var convoState = new ConversationState(dataStore); options.State.Add(convoState); // Create and add user state. var userState = new UserState(dataStore); options.State.Add(userState); // Translation key from settings var translatorKey = Configuration.GetValue <string>("translatorKey"); if (string.IsNullOrEmpty(translatorKey)) { throw new InvalidOperationException("Microsoft Text Translation API key is missing. Please add your translation key to the 'translatorKey' setting."); } // Translation middleware setup var translator = new MicrosoftTranslator(translatorKey); var translationMiddleware = new TranslationMiddleware(translator, userState.CreateProperty <string>("LanguagePreference")); options.Middleware.Add(translationMiddleware); }); // Create and register state accessors. // Accessors created here are passed into the IBot-derived class on every turn. services.AddSingleton(sp => { // We need to grab the conversationState we added on the options in the previous step 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."); } var userState = options.State.OfType <UserState>().FirstOrDefault(); if (userState == null) { throw new InvalidOperationException("UserState must be defined and added before adding user-scoped state accessors."); } // Create the custom state accessor. // State accessors enable other components to read and write individual properties of state. var accessors = new MultiLingualBotAccessors(conversationState, userState) { ConversationDialogState = conversationState.CreateProperty <DialogState>("DialogState"), LanguagePreference = userState.CreateProperty <string>("LanguagePreference"), }; return(accessors); }); }
/// <summary> /// Initializes a new instance of the <see cref="AdapterWithErrorHandler"/> class. /// </summary> /// <param name="configuration">Configuration</param> /// <param name="credentialProvider">Credential Providre</param> /// <param name="httpClient">Http Client</param> /// <param name="logger">logger</param> /// <param name="conversationState">conversationState</param> public AdapterWithErrorHandler(ICredentialProvider credentialProvider, IChannelProvider channelProvider, ConversationState conversationState, ILogger <BotFrameworkHttpAdapter> logger, TranslationMiddleware translationMiddleware) : base(credentialProvider, channelProvider, logger) { if (translationMiddleware != null) { // Add translation middleware to the adapter's middleware pipeline logger.LogInformation("Using translation middleware"); this.Use(translationMiddleware); } 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 SendWithoutMiddleware(turnContext, "An unknown error occurred, please try again or if the error persists please notify the RFP CoE."); 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 AdapterWithErrorHandler(ICredentialProvider credentialProvider, ILogger <BotFrameworkHttpAdapter> logger, HeroCardsTranslationMiddleware heroCardsTranslationMiddleware, TranslationMiddleware translationMiddleware, ConversationState conversationState = null) : base(credentialProvider) { // Use translation middleware if (translationMiddleware == null) { throw new NullReferenceException(nameof(translationMiddleware)); } Use(translationMiddleware); // Use hero cards translation middleware if (heroCardsTranslationMiddleware == null) { throw new NullReferenceException(nameof(heroCardsTranslationMiddleware)); } Use(heroCardsTranslationMiddleware); 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."); 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(ICredentialProvider credentialProvider, ILogger <BotFrameworkHttpAdapter> logger, TranslationMiddleware translationMiddleware) : base(credentialProvider) { if (credentialProvider == null) { throw new NullReferenceException(nameof(credentialProvider)); } if (logger == null) { throw new NullReferenceException(nameof(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 caught : {exception.Message}"); // Send a catch-all apology to the user. await turnContext.SendActivityAsync("Sorry, it looks like something went wrong."); }; }
public void TranslatorMiddleware_ConstructWSLocale() { var mockHttp = new MockHttpMessageHandler(); var tm = new TranslationMiddleware(new[] { "en" }, _translatorKey, httpClient: mockHttp.ToHttpClient(), defaultLocale: " "); }
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 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); }; }