From 08115c8b777aedcd162ebf4fa558175e665bc96b Mon Sep 17 00:00:00 2001 From: Stuart Ferguson Date: Sat, 22 Jan 2022 11:54:14 +0000 Subject: [PATCH 1/2] Startup refactored --- FileProcessor.Tests/BootstrapperTests.cs | 66 +++ .../FileProcessor.Tests.csproj | 1 + .../Bootstrapper/MiddlewareRegistry.cs | 391 ++++++++++++++++++ FileProcessor/FileProcessor.csproj | 2 + FileProcessor/Program.cs | 47 +-- FileProcessor/Startup.cs | 257 +----------- 6 files changed, 480 insertions(+), 284 deletions(-) create mode 100644 FileProcessor.Tests/BootstrapperTests.cs create mode 100644 FileProcessor/Bootstrapper/MiddlewareRegistry.cs diff --git a/FileProcessor.Tests/BootstrapperTests.cs b/FileProcessor.Tests/BootstrapperTests.cs new file mode 100644 index 0000000..e3124be --- /dev/null +++ b/FileProcessor.Tests/BootstrapperTests.cs @@ -0,0 +1,66 @@ +namespace FileProcessor.Tests +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using Lamar; + using Microsoft.AspNetCore.Hosting; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + using Moq; + using Xunit; + + public class BootstrapperTests + { + [Fact] + public void VerifyBootstrapperIsValid() + { + Mock hostingEnvironment = new Mock(); + hostingEnvironment.Setup(he => he.EnvironmentName).Returns("Development"); + hostingEnvironment.Setup(he => he.ContentRootPath).Returns("/home"); + hostingEnvironment.Setup(he => he.ApplicationName).Returns("Test Application"); + + ServiceRegistry services = new ServiceRegistry(); + Startup s = new Startup(hostingEnvironment.Object); + Startup.Configuration = this.SetupMemoryConfiguration(); + + this.AddTestRegistrations(services, hostingEnvironment.Object); + s.ConfigureContainer(services); + Startup.Container.AssertConfigurationIsValid(AssertMode.Full); + } + + private IConfigurationRoot SetupMemoryConfiguration() + { + Dictionary configuration = new Dictionary(); + + IConfigurationBuilder builder = new ConfigurationBuilder(); + + configuration.Add("ConnectionStrings:HealthCheck", "HeathCheckConnString"); + configuration.Add("SecurityConfiguration:Authority", "https://127.0.0.1"); + configuration.Add("EventStoreSettings:ConnectionString", "https://127.0.0.1:2113"); + configuration.Add("EventStoreSettings:ConnectionName", "UnitTestConnection"); + configuration.Add("EventStoreSettings:UserName", "admin"); + configuration.Add("EventStoreSettings:Password", "changeit"); + configuration.Add("AppSettings:UseConnectionStringConfig", "false"); + configuration.Add("AppSettings:SecurityService", "http://127.0.0.1"); + configuration.Add("AppSettings:MessagingServiceApi", "http://127.0.0.1"); + configuration.Add("AppSettings:EstateManagementApi", "http://127.0.0.1"); + configuration.Add("AppSettings:TransactionProcessorApi", "http://127.0.0.1"); + configuration.Add("AppSettings:DatabaseEngine", "SqlServer"); + + builder.AddInMemoryCollection(configuration); + + return builder.Build(); + } + + private void AddTestRegistrations(ServiceRegistry services, + IWebHostEnvironment hostingEnvironment) + { + services.AddLogging(); + DiagnosticListener diagnosticSource = new DiagnosticListener(hostingEnvironment.ApplicationName); + services.AddSingleton(diagnosticSource); + services.AddSingleton(diagnosticSource); + services.AddSingleton(hostingEnvironment); + } + } +} \ No newline at end of file diff --git a/FileProcessor.Tests/FileProcessor.Tests.csproj b/FileProcessor.Tests/FileProcessor.Tests.csproj index 0831ce5..547b0f5 100644 --- a/FileProcessor.Tests/FileProcessor.Tests.csproj +++ b/FileProcessor.Tests/FileProcessor.Tests.csproj @@ -8,6 +8,7 @@ + diff --git a/FileProcessor/Bootstrapper/MiddlewareRegistry.cs b/FileProcessor/Bootstrapper/MiddlewareRegistry.cs new file mode 100644 index 0000000..693cc20 --- /dev/null +++ b/FileProcessor/Bootstrapper/MiddlewareRegistry.cs @@ -0,0 +1,391 @@ +namespace FileProcessor.Bootstrapper +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.IO; + using System.IO.Abstractions; + using System.Linq; + using System.Net.Http; + using System.Reflection; + using BusinessLogic.Common; + using BusinessLogic.EventHandling; + using BusinessLogic.FileFormatHandlers; + using BusinessLogic.Managers; + using BusinessLogic.RequestHandlers; + using BusinessLogic.Requests; + using EstateManagement.Client; + using EstateReporting.Database; + using FileAggregate; + using FileImportLogAggregate; + using FIleProcessor.Models; + using Lamar; + using MediatR; + using Microsoft.AspNetCore.Authentication.JwtBearer; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Diagnostics.HealthChecks; + using Microsoft.IdentityModel.Tokens; + using Microsoft.OpenApi.Models; + using Newtonsoft.Json; + using Newtonsoft.Json.Serialization; + using SecurityService.Client; + using Shared.DomainDrivenDesign.EventSourcing; + using Shared.EntityFramework; + using Shared.EntityFramework.ConnectionStringConfiguration; + using Shared.EventStore.Aggregate; + using Shared.EventStore.EventHandling; + using Shared.EventStore.EventStore; + using Shared.EventStore.Extensions; + using Shared.Extensions; + using Shared.General; + using Shared.Repositories; + using TransactionProcessor.Client; + + /// + /// + /// + /// + public class MiddlewareRegistry : ServiceRegistry + { + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public MiddlewareRegistry() + { + this.AddHealthChecks().AddEventStore(Startup.EventStoreClientSettings, + userCredentials:Startup.EventStoreClientSettings.DefaultCredentials, + name:"Eventstore", + failureStatus:HealthStatus.Unhealthy, + tags:new[] {"db", "eventstore"}).AddEstateManagementService().AddTransactionProcessorService() + .AddSecurityService(this.ApiEndpointHttpHandler); + + this.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", + new OpenApiInfo + { + Title = "File Processor API", + Version = "1.0", + Description = "A REST Api to manage importing and processing bulk transaction files.", + Contact = new OpenApiContact + { + Name = "Stuart Ferguson", + Email = "golfhandicapping@btinternet.com" + } + }); + // add a custom operation filter which sets default values + //c.OperationFilter(); + //c.ExampleFilters(); + + //Locate the XML files being generated by ASP.NET... + var directory = new DirectoryInfo(AppContext.BaseDirectory); + var xmlFiles = directory.GetFiles("*.xml"); + + //... and tell Swagger to use those XML comments. + foreach (FileInfo fileInfo in xmlFiles) + { + c.IncludeXmlComments(fileInfo.FullName); + } + }); + + //services.AddSwaggerExamplesFromAssemblyOf(); + + this.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; + }).AddJwtBearer(options => + { + options.BackchannelHttpHandler = new HttpClientHandler + { + ServerCertificateCustomValidationCallback = (message, + certificate, + chain, + sslPolicyErrors) => true + }; + options.Authority = ConfigurationReader.GetValue("SecurityConfiguration", "Authority"); + options.Audience = ConfigurationReader.GetValue("SecurityConfiguration", "ApiName"); + + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateAudience = false, + ValidAudience = + ConfigurationReader.GetValue("SecurityConfiguration", "ApiName"), + ValidIssuer = + ConfigurationReader.GetValue("SecurityConfiguration", "Authority"), + }; + options.IncludeErrorDetails = true; + }); + + this.AddControllers().AddNewtonsoftJson(options => + { + options.SerializerSettings.Culture = new CultureInfo("en-GB"); + options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + options.SerializerSettings.TypeNameHandling = TypeNameHandling.None; + options.SerializerSettings.Formatting = Formatting.Indented; + options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; + options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); + }); + + Assembly assembly = this.GetType().GetTypeInfo().Assembly; + this.AddMvcCore().AddApplicationPart(assembly).AddControllersAsServices(); + } + + #endregion + + #region Methods + + /// + /// APIs the endpoint HTTP handler. + /// + /// The service provider. + /// + private HttpClientHandler ApiEndpointHttpHandler(IServiceProvider serviceProvider) + { + return new HttpClientHandler + { + ServerCertificateCustomValidationCallback = (message, + cert, + chain, + errors) => + { + return true; + } + }; + } + + #endregion + } + + /// + /// + /// + /// + public class MediatorRegistry : ServiceRegistry + { + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public MediatorRegistry() + { + this.AddSingleton(); + // request & notification handlers + this.AddTransient(context => { return t => context.GetService(t); }); + + this.AddSingleton, FileRequestHandler>(); + this.AddSingleton, FileRequestHandler>(); + this.AddSingleton, FileRequestHandler>(); + this.AddSingleton, FileRequestHandler>(); + this.AddSingleton, FileRequestHandler>(); + } + + #endregion + } + + /// + /// + /// + /// + public class DomainEventHandlerRegistry : ServiceRegistry + { + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public DomainEventHandlerRegistry() + { + Dictionary eventHandlersConfiguration = new Dictionary(); + + if (Startup.Configuration != null) + { + IConfigurationSection section = Startup.Configuration.GetSection("AppSettings:EventHandlerConfiguration"); + + if (section != null) + { + Startup.Configuration.GetSection("AppSettings:EventHandlerConfiguration").Bind(eventHandlersConfiguration); + } + } + + this.AddSingleton(eventHandlersConfiguration); + + this.AddSingleton>(container => type => + { + IDomainEventHandler handler = container.GetService(type) as IDomainEventHandler; + return handler; + }); + + this.AddSingleton(); + this.AddSingleton(); + } + + #endregion + } + + /// + /// + /// + /// + public class ClientRegistry : ServiceRegistry + { + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public ClientRegistry() + { + this.AddSingleton(); + this.AddSingleton(); + this.AddSingleton(); + + this.AddSingleton>(container => serviceName => { return ConfigurationReader.GetBaseServerUri(serviceName).OriginalString; }); + + var httpMessageHandler = new SocketsHttpHandler + { + SslOptions = + { + RemoteCertificateValidationCallback = (sender, + certificate, + chain, + errors) => true, + } + }; + HttpClient httpClient = new HttpClient(httpMessageHandler); + this.AddSingleton(httpClient); + } + + #endregion + } + + /// + /// + /// + /// + public class RepositoryRegistry : ServiceRegistry + { + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public RepositoryRegistry() + { + Boolean useConnectionStringConfig = bool.Parse(ConfigurationReader.GetValue("AppSettings", "UseConnectionStringConfig")); + + if (useConnectionStringConfig) + { + String connectionStringConfigurationConnString = ConfigurationReader.GetConnectionString("ConnectionStringConfiguration"); + this.AddSingleton(); + this.AddTransient(c => { return new ConnectionStringConfigurationContext(connectionStringConfigurationConnString); }); + + // TODO: Read this from a the database and set + } + else + { + this.AddEventStoreClient(Startup.ConfigureEventStoreSettings); + this.AddEventStoreProjectionManagerClient(Startup.ConfigureEventStoreSettings); + this.AddEventStorePersistentSubscriptionsClient(Startup.ConfigureEventStoreSettings); + this.AddSingleton(); + } + + this.AddSingleton(); + + this.AddSingleton, AggregateRepository>(); + this.AddSingleton, + AggregateRepository>(); + + this.AddSingleton, DbContextFactory>(); + this.AddSingleton>(cont => connectionString => + { + String databaseEngine = + ConfigurationReader.GetValue("AppSettings", "DatabaseEngine"); + + return databaseEngine switch + { + "MySql" => new EstateReportingMySqlContext(connectionString), + "SqlServer" => new EstateReportingSqlServerContext(connectionString), + _ => throw new + NotSupportedException($"Unsupported Database Engine {databaseEngine}") + }; + }); + this.AddSingleton(); + } + + #endregion + } + + /// + /// + /// + /// + public class FileRegistry : ServiceRegistry + { + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public FileRegistry() + { + IEnumerable fileProfiles = Startup.Configuration.GetSection("AppSettings:FileProfiles").GetChildren().ToList().Select(x => new + { + Name = x.GetValue("Name"), + FileProfileId = x.GetValue("Id"), + RequestType = x.GetValue("RequestType"), + ListeningDirectory = x.GetValue("ListeningDirectory"), + OperatorName = x.GetValue("OperatorName"), + LineTerminator = x.GetValue("LineTerminator"), + FileFormatHandler = x.GetValue("FileFormatHandler") + }).Select(f => + { + return new FileProfile(f.FileProfileId, + f.Name, + f.ListeningDirectory, + f.RequestType, + f.OperatorName, + f.LineTerminator, + f.FileFormatHandler); + }); + this.AddSingleton(fileProfiles.ToList()); + this.AddSingleton(); + this.AddSingleton>(container => fileFormatHandlerName => + { + if (fileFormatHandlerName == "SafaricomFileFormatHandler") + return new SafaricomFileFormatHandler(); + if (fileFormatHandlerName == "VoucherFileFormatHandler") + return new VoucherFileFormatHandler(); + + return null; + }); + } + + #endregion + } + + /// + /// + /// + /// + public class MiscRegistry : ServiceRegistry + { + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public MiscRegistry() + { + this.AddSingleton(); + this.AddSingleton(); + } + + #endregion + } +} \ No newline at end of file diff --git a/FileProcessor/FileProcessor.csproj b/FileProcessor/FileProcessor.csproj index 0aad0ec..b552422 100644 --- a/FileProcessor/FileProcessor.csproj +++ b/FileProcessor/FileProcessor.csproj @@ -6,6 +6,8 @@ + + diff --git a/FileProcessor/Program.cs b/FileProcessor/Program.cs index 05acbef..6a5bd12 100644 --- a/FileProcessor/Program.cs +++ b/FileProcessor/Program.cs @@ -17,6 +17,7 @@ namespace FileProcessor using EventStore.Client; using File.DomainEvents; using FileImportLog.DomainEvents; + using Lamar.Microsoft.DependencyInjection; using MediatR; using Microsoft.Extensions.DependencyInjection; using Shared.EventStore.EventHandling; @@ -42,6 +43,7 @@ public static IHostBuilder CreateHostBuilder(string[] args) .AddEnvironmentVariables().Build(); IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args); + hostBuilder.UseLamar(); hostBuilder.ConfigureLogging(logging => { logging.AddConsole(); @@ -53,51 +55,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) webBuilder.UseConfiguration(config); webBuilder.UseKestrel(); }); - - hostBuilder.ConfigureServices(services => - { - services.AddHostedService(provider => - { - IFileProcessorManager fileProcessorManager = - provider.GetRequiredService(); - IMediator mediator = provider.GetRequiredService(); - IFileSystem fileSystem = provider.GetRequiredService(); - FileProcessingWorker worker = - new FileProcessingWorker(fileProcessorManager, - mediator, - fileSystem); - worker.TraceGenerated += Worker_TraceGenerated; - return worker; - }); - }); - + return hostBuilder; } - - - private static void Worker_TraceGenerated(string trace, LogLevel logLevel) - { - switch (logLevel) - { - case LogLevel.Trace: - Logger.LogTrace(trace); - break; - case LogLevel.Debug: - Logger.LogDebug(trace); - break; - case LogLevel.Information: - Logger.LogInformation(trace); - break; - case LogLevel.Warning: - Logger.LogWarning(trace); - break; - case LogLevel.Error: - Logger.LogError(new Exception(trace)); - break; - case LogLevel.Critical: - Logger.LogCritical(new Exception(trace)); - break; - } - } } } diff --git a/FileProcessor/Startup.cs b/FileProcessor/Startup.cs index 38cc47a..182387f 100644 --- a/FileProcessor/Startup.cs +++ b/FileProcessor/Startup.cs @@ -18,6 +18,7 @@ namespace FileProcessor using System.Net.Http; using System.Reflection; using System.Threading; + using Bootstrapper; using BusinessLogic.Common; using BusinessLogic.EventHandling; using BusinessLogic.FileFormatHandlers; @@ -32,6 +33,7 @@ namespace FileProcessor using FileImportLog.DomainEvents; using FIleProcessor.Models; using HealthChecks.UI.Client; + using Lamar; using MediatR; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Diagnostics.HealthChecks; @@ -92,9 +94,9 @@ public Startup(IWebHostEnvironment webHostEnvironment) Startup.WebHostEnvironment = webHostEnvironment; } - private static EventStoreClientSettings EventStoreClientSettings; + internal static EventStoreClientSettings EventStoreClientSettings; - private static void ConfigureEventStoreSettings(EventStoreClientSettings settings = null) + internal static void ConfigureEventStoreSettings(EventStoreClientSettings settings = null) { if (settings == null) { @@ -123,258 +125,33 @@ private static void ConfigureEventStoreSettings(EventStoreClientSettings setting Startup.EventStoreClientSettings = settings; } + public static Container Container; + // 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) + public void ConfigureContainer(ServiceRegistry services) { ConfigurationReader.Initialise(Startup.Configuration); Startup.ConfigureEventStoreSettings(); - this.ConfigureMiddlewareServices(services); - - IEnumerable fileProfiles = Configuration.GetSection("AppSettings:FileProfiles").GetChildren().ToList().Select(x => new - { - Name = x.GetValue("Name"), - FileProfileId = x.GetValue("Id"), - RequestType = x.GetValue("RequestType"), - ListeningDirectory = x.GetValue("ListeningDirectory"), - OperatorName = x.GetValue("OperatorName"), - LineTerminator = x.GetValue("LineTerminator"), - FileFormatHandler = x.GetValue("FileFormatHandler") - - }).Select(f => - { - return new FileProfile(f.FileProfileId, f.Name, f.ListeningDirectory, f.RequestType, f.OperatorName, f.LineTerminator, f.FileFormatHandler); - }); - services.AddSingleton>(fileProfiles.ToList()); - - - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton, DbContextFactory>(); - services.AddSingleton>(cont => (connectionString) => - { - String databaseEngine = - ConfigurationReader.GetValue("AppSettings", "DatabaseEngine"); - - return databaseEngine switch - { - "MySql" => new EstateReportingMySqlContext(connectionString), - "SqlServer" => new EstateReportingSqlServerContext(connectionString), - _ => throw new - NotSupportedException($"Unsupported Database Engine {databaseEngine}") - }; - }); - - Boolean useConnectionStringConfig = Boolean.Parse(ConfigurationReader.GetValue("AppSettings", "UseConnectionStringConfig")); - - if (useConnectionStringConfig) - { - String connectionStringConfigurationConnString = ConfigurationReader.GetConnectionString("ConnectionStringConfiguration"); - services.AddSingleton(); - services.AddTransient(c => - { - return new ConnectionStringConfigurationContext(connectionStringConfigurationConnString); - }); - - // TODO: Read this from a the database and set - } - else - { - services.AddEventStoreClient(Startup.ConfigureEventStoreSettings); - services.AddEventStoreProjectionManagerClient(Startup.ConfigureEventStoreSettings); - services.AddEventStorePersistentSubscriptionsClient(Startup.ConfigureEventStoreSettings); - services.AddSingleton(); - } - - services.AddSingleton(); - services.AddSingleton(); - - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - services.AddSingleton>(container => (serviceName) => - { - return ConfigurationReader.GetBaseServerUri(serviceName).OriginalString; - }); - - var httpMessageHandler = new SocketsHttpHandler - { - SslOptions = - { - RemoteCertificateValidationCallback = (sender, - certificate, - chain, - errors) => true, - } - }; - HttpClient httpClient = new HttpClient(httpMessageHandler); - services.AddSingleton(httpClient); - - services.AddSingleton, AggregateRepository>(); - services.AddSingleton, AggregateRepository>(); - - FileCreatedEvent f = new FileCreatedEvent(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), String.Empty, - new DateTime()); - FileAddedToImportLogEvent f1 = new FileAddedToImportLogEvent(Guid.NewGuid(), - Guid.NewGuid(), - Guid.NewGuid(), - Guid.NewGuid(), - Guid.NewGuid(), - Guid.NewGuid(), - String.Empty, - String.Empty, - new DateTime()); - - TypeProvider.LoadDomainEventsTypeDynamically(); - - // request & notification handlers - services.AddTransient(context => - { - return t => context.GetService(t); - }); + services.IncludeRegistry(); + services.IncludeRegistry(); + services.IncludeRegistry(); + services.IncludeRegistry(); + services.IncludeRegistry(); + services.IncludeRegistry(); + services.IncludeRegistry(); - services.AddSingleton, FileRequestHandler>(); - services.AddSingleton, FileRequestHandler>(); - services.AddSingleton, FileRequestHandler>(); - services.AddSingleton, FileRequestHandler>(); - services.AddSingleton, FileRequestHandler>(); - - Dictionary eventHandlersConfiguration = new Dictionary(); - - if (Startup.Configuration != null) - { - IConfigurationSection section = Startup.Configuration.GetSection("AppSettings:EventHandlerConfiguration"); - - if (section != null) - { - Startup.Configuration.GetSection("AppSettings:EventHandlerConfiguration").Bind(eventHandlersConfiguration); - } - } - services.AddSingleton>(eventHandlersConfiguration); - - services.AddSingleton>(container => (type) => - { - IDomainEventHandler handler = container.GetService(type) as IDomainEventHandler; - return handler; - }); - - services.AddSingleton(); - services.AddSingleton(); - - services.AddSingleton>(container => (fileFormatHandlerName) => - { - if (fileFormatHandlerName == "SafaricomFileFormatHandler") - return new SafaricomFileFormatHandler(); - if (fileFormatHandlerName == "VoucherFileFormatHandler") - return new VoucherFileFormatHandler(); + Startup.LoadTypes(); - return null; - }); + Startup.Container = new Container(services); Startup.ServiceProvider = services.BuildServiceProvider(); - } public static IServiceProvider ServiceProvider { get; set; } - - private HttpClientHandler ApiEndpointHttpHandler(IServiceProvider serviceProvider) - { - return new HttpClientHandler - { - ServerCertificateCustomValidationCallback = (message, - cert, - chain, - errors) => - { - return true; - } - }; - } - - private void ConfigureMiddlewareServices(IServiceCollection services) - { - services.AddHealthChecks().AddEventStore(Startup.EventStoreClientSettings, - userCredentials:Startup.EventStoreClientSettings.DefaultCredentials, - name:"Eventstore", - failureStatus:HealthStatus.Unhealthy, - tags:new string[] {"db", "eventstore"}).AddEstateManagementService().AddTransactionProcessorService() - .AddSecurityService(ApiEndpointHttpHandler); - - services.AddSwaggerGen(c => - { - c.SwaggerDoc("v1", new OpenApiInfo - { - Title = "File Processor API", - Version = "1.0", - Description = "A REST Api to manage importing and processing bulk transaction files.", - Contact = new OpenApiContact - { - Name = "Stuart Ferguson", - Email = "golfhandicapping@btinternet.com" - } - }); - // add a custom operation filter which sets default values - //c.OperationFilter(); - //c.ExampleFilters(); - - //Locate the XML files being generated by ASP.NET... - var directory = new DirectoryInfo(AppContext.BaseDirectory); - var xmlFiles = directory.GetFiles("*.xml"); - - //... and tell Swagger to use those XML comments. - foreach (FileInfo fileInfo in xmlFiles) - { - c.IncludeXmlComments(fileInfo.FullName); - } - - }); - - //services.AddSwaggerExamplesFromAssemblyOf(); - - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; - }) - .AddJwtBearer(options => - { - options.BackchannelHttpHandler = new HttpClientHandler - { - ServerCertificateCustomValidationCallback = - (message, certificate, chain, sslPolicyErrors) => true - }; - options.Authority = ConfigurationReader.GetValue("SecurityConfiguration", "Authority"); - options.Audience = ConfigurationReader.GetValue("SecurityConfiguration", "ApiName"); - - options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters() - { - ValidateAudience = false, - ValidAudience = ConfigurationReader.GetValue("SecurityConfiguration", "ApiName"), - ValidIssuer = ConfigurationReader.GetValue("SecurityConfiguration", "Authority"), - }; - options.IncludeErrorDetails = true; - }); - - services.AddControllers().AddNewtonsoftJson(options => - { - options.SerializerSettings.Culture = new CultureInfo("en-GB"); - options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; - options.SerializerSettings.TypeNameHandling = TypeNameHandling.None; - options.SerializerSettings.Formatting = Formatting.Indented; - options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; - options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); - }); - - Assembly assembly = this.GetType().GetTypeInfo().Assembly; - services.AddMvcCore().AddApplicationPart(assembly).AddControllersAsServices(); - } - + public static void LoadTypes() { FileAddedToImportLogEvent fileAddedToImportLogEvent = From bd73fc39d7b0493bcaec10e98cf9130a1f04f5ae Mon Sep 17 00:00:00 2001 From: Stuart Ferguson Date: Sat, 22 Jan 2022 12:41:26 +0000 Subject: [PATCH 2/2] :| --- FileProcessor/Program.cs | 43 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/FileProcessor/Program.cs b/FileProcessor/Program.cs index 6a5bd12..655e810 100644 --- a/FileProcessor/Program.cs +++ b/FileProcessor/Program.cs @@ -55,8 +55,49 @@ public static IHostBuilder CreateHostBuilder(string[] args) webBuilder.UseConfiguration(config); webBuilder.UseKestrel(); }); - + hostBuilder.ConfigureServices(services => + { + services.AddHostedService(provider => + { + IFileProcessorManager fileProcessorManager = + provider.GetRequiredService(); + IMediator mediator = provider.GetRequiredService(); + IFileSystem fileSystem = provider.GetRequiredService(); + FileProcessingWorker worker = + new FileProcessingWorker(fileProcessorManager, + mediator, + fileSystem); + worker.TraceGenerated += Worker_TraceGenerated; + return worker; + }); + }); + return hostBuilder; } + + private static void Worker_TraceGenerated(string trace, LogLevel logLevel) + { + switch (logLevel) + { + case LogLevel.Trace: + Logger.LogTrace(trace); + break; + case LogLevel.Debug: + Logger.LogDebug(trace); + break; + case LogLevel.Information: + Logger.LogInformation(trace); + break; + case LogLevel.Warning: + Logger.LogWarning(trace); + break; + case LogLevel.Error: + Logger.LogError(new Exception(trace)); + break; + case LogLevel.Critical: + Logger.LogCritical(new Exception(trace)); + break; + } + } } }