using Blazored.LocalStorage; using Blazored.SessionStorage; using HealthChecks.UI.Client; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.AspNetCore.Localization; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.FileProviders; using StackExchange.Redis; using System.Globalization; using System.Text.Json.Serialization; using WebDoorCreator.Data; using WebDoorCreator.Data.Services; using WebDoorCreator.UI.Areas.Identity; using WebDoorCreator.UI.Data; var builder = WebApplication.CreateBuilder(args); // configuration setup Microsoft.Extensions.Configuration.ConfigurationManager configuration = builder.Configuration; // REDIS setup string connStringRedis = configuration.GetConnectionString("Redis"); if (string.IsNullOrEmpty(connStringRedis)) { connStringRedis = "localhost:6379, DefaultDatabase=11, connectTimeout=5000, syncTimeout=5000, asyncTimeout=5000, abortConnect=false, ssl=false"; } string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":")); // avvio oggetto shared x redis... var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); // AspNetCore Identity setup var connectionString = configuration.GetConnectionString("Identity.DB"); string dbServerAddr = "127.0.0.1"; if (string.IsNullOrEmpty(connectionString)) { connectionString = "Server=SQL2016DEV;Database=WebDoorCreator; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=WebDoorCreator.SRV;"; } else { if (connectionString.Contains("Server")) { bool trovato = false; var dbTokens = connectionString.Split(";"); int numTok = dbTokens.Count(); int idx = 0; while (!trovato && idx < numTok) { if (dbTokens[idx].StartsWith("Server=")) { // rimuovo la chaive Server... dbServerAddr = dbTokens[idx].Replace("Server=", ""); // se ci fosse un nome (tipo \\sqlexpress) rimuovo... if (dbServerAddr.Contains("\\")) { int sIdx = dbServerAddr.IndexOf("\\"); dbServerAddr = dbServerAddr.Substring(0, sIdx); } trovato = true; } idx++; } } } // healthchecks builder.Services.AddHealthChecks() .AddSqlServer(connectionString, healthQuery: "SELECT 1;", name: "SqlServer", failureStatus: HealthStatus.Degraded, tags: new string[] { "DB", "MsSql" }) .AddAsyncCheck($"DB PING ({dbServerAddr})", () => WebDoorCreator.UI.Health.Checks.PingCheck(dbServerAddr)) .AddAsyncCheck($"Redis PING ({redisSrvAddr})", () => WebDoorCreator.UI.Health.Checks.PingCheck(redisSrvAddr)) // 512 MB max allocated memory .AddProcessAllocatedMemoryHealthCheck(512, "Max Process memory (<512MB)", failureStatus: HealthStatus.Degraded) .AddRedis(connStringRedis, "Redis", failureStatus: HealthStatus.Degraded) .AddAsyncCheck($"Config Table", () => WebDoorCreator.UI.Health.Checks.ConfigCount(configuration)) .AddAsyncCheck($"Orders Table", () => WebDoorCreator.UI.Health.Checks.OrdersCount(configuration)) .AddAsyncCheck($"Doors Table", () => WebDoorCreator.UI.Health.Checks.DoorsCount(configuration)) ; #if false builder.Services .AddHealthChecksUI(s => { s.AddHealthCheckEndpoint("WDC_UI_HC", "health"); s.SetEvaluationTimeInSeconds(60); s.SetMinimumSecondsBetweenFailureNotifications(120); s.SetApiMaxActiveRequests(5); s.SetHeaderText("WDC.UI Health Check Status"); }) .AddInMemoryStorage(); #endif // abilitazione x email management con MailKit builder.Services.AddTransient(); builder.Services.Configure(options => { options.Host_Address = configuration["ExternalProviders:MailKit:SMTP:Address"]; options.Host_Port = Convert.ToInt32(configuration["ExternalProviders:MailKit:SMTP:Port"]); options.Host_Username = configuration["ExternalProviders:MailKit:SMTP:Account"]; options.Host_Password = configuration["ExternalProviders:MailKit:SMTP:Password"]; options.Sender_EMail = configuration["ExternalProviders:MailKit:SMTP:SenderEmail"]; options.Sender_Name = configuration["ExternalProviders:MailKit:SMTP:SenderName"]; }); // aggiunta servizi x accesso dati... builder.Services.AddControllers() .AddJsonOptions(c => c.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve); // Add services to the container. builder.Services.AddDbContext(options => options.UseSqlServer(connectionString)); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddRoles() .AddEntityFrameworkStores(); builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); ; builder.Services.AddSingleton(redisMultiplexer); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped>(); builder.Services.AddHttpContextAccessor(); builder.Services.AddBlazoredLocalStorage(); builder.Services.AddBlazoredSessionStorage(); var app = builder.Build(); // aggiunt base URL x routing corretto app.UsePathBase(configuration["RuntimeOpt:BaseUrl"]); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseMigrationsEndPoint(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } // cultura US... var supportedCultures = new[]{ new CultureInfo("en-US") }; app.UseRequestLocalization(new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture("en-US"), SupportedCultures = supportedCultures, FallBackToParentCultures = false }); CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("en-US"); app.UseHttpsRedirection(); app.UseStaticFiles(); // gestione static files: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-8.0 string BasePathPdf = configuration.GetValue("ServerConf:BasePathPdf") ?? configuration.GetValue("OptConf:BasePathPdf") ?? ""; if (!string.IsNullOrEmpty(BasePathPdf)) { // verifico esista folder disegni if (Directory.Exists(BasePathPdf)) { // gestione cartella x PDF app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(BasePathPdf), RequestPath = "/docs", }); } } app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.MapBlazorHub(); // config healthcheck: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks // prende tutti i predicati app.MapHealthChecks("/health", new HealthCheckOptions { Predicate = _ => true, ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse }); // opzionalmente si puo' aggiungere richiesta AUTH //.RequireAuthorization(); // nasconde tutti i dettagli app.MapHealthChecks("/health/live", new HealthCheckOptions { Predicate = _ => false }); app.MapFallbackToPage("/_Host"); app.Run();