コード例 #1
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add Singletons
            services.AddSingleton <IEnvironmentInformationProvider>(new EnvironmentInformationProvider(RuntimeEnvironment));

            // Ensure nothing non-secure passes to any controller
            if (!RuntimeEnvironment.IsDevelopment() && !RuntimeEnvironment.EnvironmentName.Equals("Local", StringComparison.InvariantCultureIgnoreCase) && UseHsts())
            {
                services.Configure <MvcOptions>(o => o.Filters.Add(new RequireHttpsAttribute()));

                // TODO: We need to register codeswifterstarter.com to the list of hsts preloaded domains https://hstspreload.org/
                services.AddHsts(o =>
                {
                    o.MaxAge            = TimeSpan.FromDays(365);
                    o.Preload           = true;
                    o.IncludeSubDomains = true;
                });
            }

            if (!RuntimeEnvironment.IsDevelopment() && !RuntimeEnvironment.EnvironmentName.Equals("Local", StringComparison.InvariantCultureIgnoreCase) && UseSSL())
            {
                services.AddHttpsRedirection(options =>
                {
                    options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
                });
            }


            services.AddHttpContextAccessor();
            services.AddScoped <HttpContextAccessor>();

            _serverConfiguration = ConfigurationHelper <ServerConfiguration> .GetConfigurationFromJson(RuntimeEnvironment);

            services.AddSingleton(_serverConfiguration);

            // Add AutoMapper
            services.AddSingleton <IMapper>(new Mapper(new MapperConfiguration(cfg =>
            {
                cfg.AddProfile <AutoMapperProfile>();
            })));

            // Add framework services.
            services.AddTransient <INotificationService, NotificationService>();
            services.AddTransient <IFileStorageService, FileStorageService>();
            services.AddTransient <ICrudWarningService, CrudWarningService>();
            services.AddTransient <IDateTime, MachineDateTime>();

            // Register AuthenticatedUserService service
            services.AddScoped <IAuthenticatedUserService, AuthenticatedUserService>();
            services.AddScoped <IAuthManagementService, AuthManagementService>();

            // Register all query managers
            services.AddScopedForClassesEndingWith(typeof(AutoMapperProfile).GetTypeInfo().Assembly, "QueryManager");

            // Add MediatR
            services.AddTransient(typeof(IPipelineBehavior <,>), typeof(RequestPreProcessorBehavior <,>));
            services.AddTransient(typeof(IPipelineBehavior <,>), typeof(RequestPerformanceBehaviour <,>));
            services.AddTransient(typeof(IPipelineBehavior <,>), typeof(RequestValidationBehavior <,>));
            services.AddMediatR(typeof(AutoMapperProfile).GetTypeInfo().Assembly);

            // Add database context
            services.AddDbContext <CodeSwifterStarterDbContext>(_serverConfiguration.ConnectionStrings
                                                                .CodeSwifterStarterDatabase);
            services.AddScoped(service =>
                               (ICodeSwifterStarterDbContext)service.GetService(typeof(CodeSwifterStarterDbContext)));

            // Add seeder
            services.AddScoped <CodeSwifterStarterDbSeeder>();

            // Add support for proper validation return messages
            services
            .AddMvc(options => options.Filters.Add(typeof(CustomExceptionFilterAttribute)))
            .AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore)
            .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining <AutoMapperProfile>());

            services.AddDataProtection(o => { o.ApplicationDiscriminator = "CodeSwifterStarter"; });

            services.Configure <BrotliCompressionProviderOptions>
                (options => options.Level = CompressionLevel.Fastest);

            services.Configure <GzipCompressionProviderOptions>
                (options => options.Level = CompressionLevel.Fastest);

            services.AddResponseCompression(options =>
            {
                options.EnableForHttps = true;
                options.Providers.Add <BrotliCompressionProvider>();
                options.Providers.Add <GzipCompressionProvider>();
                options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[]
                {
                    "image/svg+xml", "image/jpeg", "image/png", "text/html", "application/javascript",
                    "application/json", "text/json", "text/css"
                });
            });

            services.AddControllers();

            if (!RuntimeEnvironment.IsDevelopment() && !RuntimeEnvironment.EnvironmentName.Equals("Local", StringComparison.InvariantCultureIgnoreCase))
            {
                services.Configure <ForwardedHeadersOptions>(options =>
                {
                    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
                    options.ForwardLimit     = 2;
                });
            }

            services.AddSpaStaticFiles(configuration => { configuration.RootPath = "ClientApp/dist"; });

            services
            .AddMvc(options => { options.Filters.Add(typeof(CustomExceptionFilterAttribute)); })
            .AddNewtonsoftJson()
            .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);


            // Add authentication services
            services.Configure <CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded    = context => RuntimeEnvironment.IsProduction() || RuntimeEnvironment.IsStaging();
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                options.Authority = _serverConfiguration.SecurityProvider.Authority;
                options.Audience  = _serverConfiguration.SecurityProvider.SingleSignOn.Api.Audience;
            });

            var authDomain = _serverConfiguration.SecurityProvider.Authority;

            services.AddAuthorization(options =>
            {
                foreach (var securityPolicy in SecurityPoliciesFactory.Policies)
                {
                    options.AddPolicy(securityPolicy.Name,
                                      policy =>
                    {
                        foreach (var permission in securityPolicy.Permissions)
                        {
                            policy.Requirements.Add(new PermissionRequirement(permission.Name, authDomain));
                        }
                    });
                }
            });

            // register the scope authorization handler
            services.AddScoped <IAuthorizationHandler, PermissionHandler>();

            // Consider making this publicly available
            if (RuntimeEnvironment.IsDevelopment() ||
                RuntimeEnvironment.EnvironmentName.Equals("Local", StringComparison.InvariantCultureIgnoreCase))
            {
                services.AddSwaggerDocument(settings =>
                {
                    settings.Title = "CodeSwifterStarter API";
                });
            }

            // Customise default API behavour
            services.Configure <ApiBehaviorOptions>(options =>
            {
                if (RuntimeEnvironment.IsProduction() || RuntimeEnvironment.IsStaging())
                {
                    options.SuppressModelStateInvalidFilter = true;
                }
            });
        }