/// <summary> /// We use constructor dependency injection to the interfaces we need at runtime /// </summary> /// <param name="InitialConfiguration"></param> /// <param name="ApplicationSecrets"></param> /// <param name="Configuration"></param> public MyApplication(IApplicationSetupConfiguration InitialConfiguration, IApplicationSecrets ApplicationSecrets, IConfiguration Configuration) { _InitialConfiguration = InitialConfiguration; _ApplicationSecrets = ApplicationSecrets; _Configuration = Configuration; }
/// <summary> /// This method will create an initialize a generic Host Builder /// </summary> /// <typeparam name="TApp">Main application type. Used to access user secrets</typeparam> /// <param name="args">Application arguments</param> /// <param name="localServiceConfiguration">Delegate to be executed to add any non-standard configuration needs</param> /// <returns>Configured IHostBuilder</returns> public static IHostBuilder CreateHostBuilder <TApp>(string[] args, ConfigureLocalServices <TApp> localServiceConfiguration = null) where TApp : class { IApplicationSecrets appSecrets = null; IApplicationSetupConfiguration appIntialConfig = null; IAppConfigSections sections = null; IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, builder) => { sections = ConfigFactory.Initialize <TApp>(hostingContext, builder); appSecrets = sections.appSecrets; appIntialConfig = sections.appIntialConfig; }) .ConfigureServices((hostingContext, services) => { localServiceConfiguration?.Invoke(hostingContext, services, sections); services .AddTransient <TApp>() .AddSingleton <IApplicationSetupConfiguration>(sp => { return(appIntialConfig); }) .AddSingleton <IApplicationSecrets>(sp => { return(appSecrets); }) .AddSingleton <IHostEnvironment>(sp => { return(hostingContext.HostingEnvironment); }) .AddSingleton <IApplicationRequirements <TApp>, ApplicationRequirements <TApp> >(); services.BuildServiceProvider(); }) .ConfigureLogging((hostingContext, logging) => { ConfigureCustomLogging(hostingContext, logging, appSecrets, appIntialConfig); }); return(hostBuilder); }
public ApplicationRequirements(ILogger <T> applicationLogger, IApplicationSecrets applicationSecrets, IConfiguration applicationConfiguration, IApplicationSetupConfiguration applicationSetupConfiguration, IHostEnvironment hostEnvironment) { try { this.applicationSecrets = applicationSecrets; this.ApplicationLogger = applicationLogger; this.ApplicationConfiguration = applicationConfiguration; this.ApplicationSetupConfiguration = applicationSetupConfiguration; this.HostEnvironment = hostEnvironment; TraceLoggerExtension._HostEnvironment = hostEnvironment; TraceLoggerExtension._environmentName = applicationSetupConfiguration.RTE; TraceLoggerExtension._Logger = applicationLogger; TraceLoggerExtension._SerializationFormat = applicationSetupConfiguration.SerializationFormat; } catch { } }
/// <summary> /// If the default factory method "ConsoleHostBuilderHelper.CreateApp" does not support all the services /// you need at runtime, then you can add them here. "CreateApp" calls this method before any other services /// are added to the IServiceCollection. /// </summary> /// <param name="hostingContext">HostBuilderContext</param> /// <param name="services">IServiceCollection</param> /// <param name="InitialConfiguration">IApplicationSetupConfiguration</param> public static void ConfigureLocalServices(HostBuilderContext hostingContext, IServiceCollection services, IApplicationSetupConfiguration InitialConfiguration) { // Register the appropriate interfaces depending on the environment bool useKeyVaultKey = !string.IsNullOrEmpty(InitialConfiguration.KeyVaultKey); // .... Any custom configuration you need can be done here .......... }
/// <summary> /// Different types of logging are enabled based on the MyProjectSettings:EnabledLoggers: [ "File", "Console", "Debug" ] /// </summary> /// <param name="hostingContext">Generic host builder context used to configure the application</param> /// <param name="logging">Interface used to configure logging providers</param> /// <param name="applicationSecrets">Interface used to access all properties in the "ApplicationSecrets" property of the appsettings.json file</param> /// <param name="applicationSetupConfiguration">Interface used to access all properties in the "InitialConfiguration" property of the appsettings.json file</param> public static void ConfigureCustomLogging(HostBuilderContext hostingContext, ILoggingBuilder logging, IApplicationSecrets applicationSecrets, IApplicationSetupConfiguration applicationSetupConfiguration) { TraceLoggerExtension._HostEnvironment = hostingContext.HostingEnvironment; TraceLoggerExtension._SerializationFormat = applicationSetupConfiguration.SerializationFormat; logging.ClearProviders(); if (applicationSetupConfiguration.IsLoggingEnabled) { logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); if (applicationSetupConfiguration.IsLoggerEnabled(EnabledLoggersEnum.Debug)) { logging.AddDebug(); } if (applicationSetupConfiguration.IsLoggerEnabled(EnabledLoggersEnum.Console)) { logging.AddConsole(); } if (applicationSetupConfiguration.IsLoggerEnabled(EnabledLoggersEnum.File)) { // The FileLogger will be configured for log4Net local logging during development. string logConnectionString = applicationSecrets.ConnectionString("FileLogger"); // Must set the log name prior to adding Log4Net because it must know this value // before it loads the config file. It does pattern matching and substitution on the filename. string logPath = null; string logName = null; if (!string.IsNullOrEmpty(logConnectionString)) { string[] logParts = logConnectionString.Split(";"); logPath = logParts[0]?.Replace("LogPath=", ""); logName = logParts[1]?.Replace("LogName=", ""); } if (!string.IsNullOrEmpty(logPath)) { if (!Directory.Exists(logPath)) { Directory.CreateDirectory(logPath); } logName = $"{logPath}\\{logName}"; } log4net.GlobalContext.Properties["LogName"] = logName; logging.AddLog4Net("log4net.config"); } } }
/// <summary> /// The appsettings section "ApplicationSecrets" contains all connection string and sensitive information. /// To hide this information from source control and to allow individual developers to have their own settings /// we copy the section "ApplicationSecrets" into the secrets.json file for local development. /// In production this value will come from KeyVault. This method reads the appropriate values /// can generates the final IApplicationSecrets that will be used at runtime. /// </summary> /// <param name="configuration">IConfigurationRoot</param> /// <param name="applicationSetupConfiguration">IApplicationSetupConfiguration</param> /// <returns>IApplicationSecrets containing contents of the "ApplicationSecrets" section of configuration</returns> public static IApplicationSecrets InitializeApplicationSecrets(IConfigurationRoot configuration, IApplicationSetupConfiguration applicationSetupConfiguration) { ApplicationSecrets retVal = null; try { if (!string.IsNullOrEmpty(applicationSetupConfiguration.KeyVaultKey)) { string mySecret = configuration[applicationSetupConfiguration.KeyVaultKey]; string decoded = Base64Decode(mySecret); JObject jo = JObject.Parse(decoded); string val = jo.Properties().First(x => x.Name == ApplicationSecretsSectionName).Value.ToString(); retVal = JsonConvert.DeserializeObject <ApplicationSecrets>(val); } } catch (Exception Err) { } // Bind the local configuration properties to the properties in the ApplicationSecrets object IConfigurationSection myConfiguration = configuration.GetSection(ApplicationSecretsSectionName); ApplicationSecrets localSecrets = new ApplicationSecrets(); myConfiguration.Bind(localSecrets); // If the local configuration contains secrets that were not present in KeyVault, then include them if (retVal != null) { foreach (ApplicationSecretsConnectionStrings nextSecret in localSecrets.ConnectionStrings) { // Try to find the local secret name in the KeyVault version. If not found in KeyVault, then insert it // into final merge. IApplicationSecretsConnectionStrings found = retVal.Secret(nextSecret.Name); if (found == null) { retVal.ConnectionStrings.Add(nextSecret); } } } else { retVal = localSecrets; } return(retVal); }
/// <summary> /// Different types of logging are enabled based on the MyProjectSettings:EnabledLoggers: [ "File", "Console", "Debug" ] /// </summary> /// <param name="hostingContext">Generic host builder context used to configure the application</param> /// <param name="logging">Interface used to configure logging providers</param> /// <param name="applicationSecrets">Interface used to access all properties in the "ApplicationSecrets" property of the appsettings.json file</param> /// <param name="applicationSetupConfiguration">Interface used to access all properties in the "InitialConfiguration" property of the appsettings.json file</param> public static void ConfigureCustomLogging(HostBuilderContext hostingContext, ILoggingBuilder logging, IApplicationSecrets applicationSecrets, IApplicationSetupConfiguration applicationSetupConfiguration) { logging.ClearProviders(); if (applicationSetupConfiguration.IsLoggingEnabled) { logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); if (applicationSetupConfiguration.IsLoggerEnabled(EnabledLoggersEnum.Debug)) { logging.AddDebug(); } if (applicationSetupConfiguration.IsLoggerEnabled(EnabledLoggersEnum.Console)) { logging.AddConsole(); } if (applicationSetupConfiguration.IsLoggerEnabled(EnabledLoggersEnum.File)) { // The FileLogger will be configured for log4Net local logging during development. // It will contain the instrumentation key for Azure Application Insights when // the connection information is coming from KeyVault string logConnectionString = applicationSecrets.ConnectionString("FileLogger"); Guid gKey; if (!string.IsNullOrEmpty(applicationSetupConfiguration.KeyVaultKey) && Guid.TryParse(logConnectionString, out gKey)) { string instrumentationKey = logConnectionString; logging.AddApplicationInsights(instrumentationKey); // Adding the filter below to ensure logs of all severities // is sent to ApplicationInsights. logging.AddFilter <Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider> ("RemoteLogging", LogLevel.Debug); } else // No local KeyVaultKey or environment setting for InitialConfiguration_KeyVaultKey found, so use local Log4Net logging { // Must set the log name prior to adding Log4Net because it must know this value // before it loads the config file. It does pattern matching and substitution on the filename. string logPath = null; string logName = null; if (!string.IsNullOrEmpty(logConnectionString)) { string[] logParts = logConnectionString.Split(";"); logPath = logParts[0]?.Replace("LogPath=", ""); logName = logParts[1]?.Replace("LogName=", ""); } if (!string.IsNullOrEmpty(logPath)) { if (!Directory.Exists(logPath)) { Directory.CreateDirectory(logPath); } logName = $"{logPath}\\{logName}"; } log4net.GlobalContext.Properties["LogName"] = logName; logging.AddLog4Net("log4net.config"); } } } }