using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Microsoft.Net.Http.Headers; using Sarand.Net.Standard.Base.App; using Sarand.Net.Standard.Base.Core; using Saxonite.Net.Core.Web.Base.Middleware; using Saxonite.Net.Standard.Base.App; using System; using System.Collections.Generic; using System.Globalization; using System.Net.Http; using System.Text; namespace Saxonite.Net.Core.Web.Base.App { //======================================================================= public class SaxStartup { //------------------------------------------------------------------- // Data members. // Localisation. private static RequestCulture defaultRequestCulture = new RequestCulture("en-GB", "en-GB"); private static List supportedCultures = new List { new CultureInfo("en-GB"), new CultureInfo("en-US"), new CultureInfo("en"), new CultureInfo("fr-FR"), new CultureInfo("fr"), }; //------------------------------------------------------------------- // Protected construction. protected SaxStartup(IConfiguration configuration) { Configuration = configuration; } //------------------------------------------------------------------- // Properties. public IConfiguration Configuration { get; } public static RequestCulture DefaultRequestCulture { get { return defaultRequestCulture; } } public static List SupportedCultures { get { return new List(supportedCultures); } } //------------------------------------------------------------------- // This method gets called by the runtime. Use this method to add services to the container. protected class ConfigureServicesConfig { public IServiceCollection services; public String sessionCookieName; public bool sessionCookieHttpOnly; public TimeSpan sessionIdleTimeout; } protected void ConfigureServices(ConfigureServicesConfig config) { // Authentication service. // Required to handle 'Forbidden' responses etc. config.services .AddAuthentication(options => { options.DefaultAuthenticateScheme = "forbidScheme"; options.DefaultForbidScheme = "forbidScheme"; options.AddScheme("forbidScheme", "Handle Forbidden"); }); // Added to support memory caching of sessions. config.services.AddMemoryCache(); //config.services.AddDistributedMemoryCache(); - for multiple web servers. // Online web application cookie definition. config.services.AddSession (options => { options.Cookie.Name = config.sessionCookieName; options.Cookie.HttpOnly = config.sessionCookieHttpOnly; options.IdleTimeout = config.sessionIdleTimeout; // Override cookie policy for session cookie. Ref. config.app.UseCookiePolicy() options.Cookie.IsEssential = true; } ); // Localisation properties folder. String resourcesPath = "Localisation"; config.services.AddLocalization(opts => { opts.ResourcesPath = resourcesPath; }); // Modify pages during debug. #if DEBUG if (SaxSystem.DebugMode) // If the following line throws an error such as: // 'imvcbuilder' does not contain a definition for 'addrazorruntimecompilation' // Revert the NuGet Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation package // to a previous version and then reinstal the latest version. config.services.AddRazorPages().AddRazorRuntimeCompilation(); #endif config.services.AddMvc (options => { // Model binding - intercepting form values being bound to models. options.ModelBinderProviders.Insert(0, new SaxModelBinderProvider()); // Blank form values to be populated to model as empty strings rather than null values. options.ModelMetadataDetailsProviders.Add(new SaxMetadataProvider()); } ) // View and data annotation localisations. .AddViewLocalization( LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = resourcesPath; }) .AddDataAnnotationsLocalization() // Ignore null values during object serisliation. .AddJsonOptions(options => { options.JsonSerializerOptions.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull; }); // Configure localisation middleware. config.services.Configure (opts => { // Default culture to use for requests. opts.DefaultRequestCulture = DefaultRequestCulture; // Cultures supported by the application. Formatting numbers, dates, etc. opts.SupportedCultures = SupportedCultures; // UI cultures supported by the application. UI strings that have been localized. opts.SupportedUICultures = SupportedCultures; } ); // Allows access to the HttpContext inside a service. config.services.AddSingleton(); } //------------------------------------------------------------------- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. protected class ConfigureConfig { public IApplicationBuilder app; public IHostApplicationLifetime hostApplicationLifetime; public IWebHostEnvironment env; } protected void Configure(ConfigureConfig config) { if (config.env.IsDevelopment()) { config.app.UseDeveloperExceptionPage(); } else { config.app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. config.app.UseHsts(); } config.app.UseHttpsRedirection(); config.app.UseStaticFiles(); config.app.UseCookiePolicy(); config.app.UseSession(); config.app.UseRouting(); //config.app.UseAuthorization(); config.app.UseAntiforgeryTokens(); // Localisation. IOptions localizationOptions = config.app.ApplicationServices.GetService>(); config.app.UseRequestLocalization(localizationOptions.Value); config.app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); // Application events. // NB The shutdown events only fire if he application stops 'gracefully'. config.hostApplicationLifetime.ApplicationStarted.Register(OnApplicationStarted); config.hostApplicationLifetime.ApplicationStopping.Register(OnApplicationStopping); config.hostApplicationLifetime.ApplicationStopped.Register(OnApplicationStopped); config.app.Use(async (context, next) => { if (context.Request.Method.Equals(HttpMethod.Get.Method)) { context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue() { Public = true, MaxAge = TimeSpan.FromSeconds(10) }; //context.Response.Headers[HeaderNames.Vary] = new string[] { "Accept-Encoding" }; } await next(); }); } //------------------------------------------------------------------- // Application events. private readonly static String ApplicationEventLogPrefix = "### "; private void OnApplicationStarted() { SaLogger.Info(ApplicationEventLogPrefix + "Application started"); } private void OnApplicationStopping() { SaLogger.Info(ApplicationEventLogPrefix + "Application stopping"); } private void OnApplicationStopped() { SaLogger.Info(ApplicationEventLogPrefix + "Application stopped"); } //------------------------------------------------------------------- } //======================================================================= }