/// <summary> /// This method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services">The service collection.</param> public void ConfigureServices(IServiceCollection services) { var allowedCorsOrigins = Configuration["AllowedCorsOrigins"]?.Split(',') ?? new string[0]; services.AddCors(options => { options.AddPolicy( "AllowSpecificOrigins", builder => builder.WithOrigins(allowedCorsOrigins).AllowCredentials().AllowAnyMethod().AllowAnyHeader()); }); var defaultSerializer = new DefaultJsonSerializer(); services.AddOptions(); services.Configure <AppSettings>(Configuration.GetSection("AppSettings")); services.AddLogging(builder => { builder .AddConfiguration(Configuration.GetSection("Logging")) .AddConsole(); }); // Add hosted services services.AddHostedService <ProcessObjectHostedService>(); // TODO: replace InMemoryUnitOfWork with SQLite services.AddScoped <IAmiUnitOfWork, InMemoryUnitOfWork>(); services.AddScoped <IIdGenService, IdGenService>(); services.AddScoped <IImageService, ImageService>(); services.AddScoped <IImageExtractor, ItkImageExtractor>(); services.AddScoped <IGifImageWriter, AnimatedGifImageWriter>(); services.AddScoped <IDefaultJsonWriter, DefaultJsonWriter>(); services.AddScoped <IChunkedObjectUploader, ChunkedObjectUploader>(); services.AddSingleton <IApplicationConstants, ApplicationConstants>(); services.AddSingleton <IFileSystemStrategy, FileSystemStrategy>(); services.AddSingleton <IAppInfoFactory, AppInfoFactory>(); services.AddSingleton <IItkImageReaderFactory, ItkImageReaderFactory>(); services.AddSingleton <IApiConfiguration, ApiConfiguration>(); services.AddSingleton <IAmiConfigurationManager, AmiConfigurationManager>(); services.AddSingleton <ITaskQueue, TaskQueue>(); services.AddSingleton <ITaskWorker, TaskWorker>(); services.AddTransient <IDefaultJsonSerializer, DefaultJsonSerializer>(); services.AddTransient <ICustomExceptionHandler, CustomExceptionHandler>(); // Add MediatR services.AddTransient(typeof(IPipelineBehavior <,>), typeof(RequestPreProcessorBehavior <,>)); services.AddTransient(typeof(IPipelineBehavior <,>), typeof(RequestPerformanceBehavior <,>)); services.AddTransient(typeof(IPipelineBehavior <,>), typeof(RequestValidationBehavior <,>)); services.AddMediatR(typeof(GetQueryHandler).GetTypeInfo().Assembly); // Add DbContext services.AddDbContext <InMemoryDbContext>(options => { options.UseInMemoryDatabase("AmiInMemoryDb", InMemoryDatabaseRoot); options.ConfigureWarnings(x => x.Ignore(InMemoryEventId.TransactionIgnoredWarning)); // remove when not using InMemory context }); services.AddMvc(options => { options.Filters.Add(typeof(CustomExceptionFilterAttribute)); options.Filters.Add(new ProducesResponseTypeAttribute(typeof(ErrorModel), (int)HttpStatusCode.BadRequest)); options.Filters.Add(new ProducesResponseTypeAttribute(typeof(ErrorModel), (int)HttpStatusCode.Unauthorized)); options.Filters.Add(new ProducesResponseTypeAttribute(typeof(ErrorModel), (int)HttpStatusCode.Forbidden)); options.Filters.Add(new ProducesResponseTypeAttribute(typeof(ErrorModel), (int)HttpStatusCode.NotFound)); options.Filters.Add(new ProducesResponseTypeAttribute(typeof(ErrorModel), (int)HttpStatusCode.Conflict)); options.Filters.Add(new ProducesResponseTypeAttribute(typeof(ErrorModel), (int)HttpStatusCode.InternalServerError)); }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining <ProcessCommandValidator>()) .AddJsonOptions(options => { defaultSerializer.OverrideJsonSerializerSettings(options.SerializerSettings); }); // Customise default API behavior services.Configure <ApiBehaviorOptions>(options => { // Otherwise the RequestValidationBehavior is never triggered options.SuppressModelStateInvalidFilter = true; }); }