From cd092f8290f749563ee1c8b1c2f2ddbb376d74d5 Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Sat, 10 Jan 2026 20:56:29 +0100 Subject: [PATCH] Restructures application startup and configuration Migrates from standalone Program.cs to Startup-based configuration Adds application configuration JSON for environment-specific settings Integrates Autofac dependency injection and modular service registration Configures application services, modules, and middleware for enhanced flexibility --- PlanTempus.Application/Program.cs | 57 +++--------- PlanTempus.Application/Startup.cs | 93 +++++++++++++++++++ PlanTempus.Application/appconfiguration.json | 19 ++++ .../Outbox/OutboxListenerModule.cs | 5 + 4 files changed, 129 insertions(+), 45 deletions(-) create mode 100644 PlanTempus.Application/Startup.cs create mode 100644 PlanTempus.Application/appconfiguration.json diff --git a/PlanTempus.Application/Program.cs b/PlanTempus.Application/Program.cs index e839d00..79380e5 100644 --- a/PlanTempus.Application/Program.cs +++ b/PlanTempus.Application/Program.cs @@ -1,47 +1,14 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.AspNetCore.Mvc.Razor; -using Microsoft.AspNetCore.Mvc.RazorPages; -using PlanTempus.Application.Features.Localization.Services; -using PlanTempus.Application.Features.Menu.Services; +using Autofac.Extensions.DependencyInjection; +using PlanTempus.Application; -var builder = WebApplication.CreateBuilder(args); +var host = Host.CreateDefaultBuilder(args) + .UseServiceProviderFactory(new AutofacServiceProviderFactory()) + .ConfigureWebHostDefaults(webHostBuilder => + { + webHostBuilder + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseStartup(); + }) + .Build(); -// Add Razor Pages with feature-based structure -builder.Services.AddRazorPages(options => -{ - options.RootDirectory = "/Features"; -}) -.AddRazorOptions(options => -{ - // View locations for partials and ViewComponents - options.ViewLocationFormats.Add("/Features/_Shared/Pages/{0}.cshtml"); - options.ViewLocationFormats.Add("/Features/_Shared/Components/{1}/{0}.cshtml"); - -}); - -// Register application services -builder.Services.AddScoped(); -builder.Services.AddScoped(); - -var app = builder.Build(); - -// Developer exception page for debugging -if (app.Environment.IsDevelopment()) -{ - app.UseDeveloperExceptionPage(); -} - -// Serve static files from wwwroot -app.UseStaticFiles(); - -// Configure routing -app.UseRouting(); - -// Map Razor Pages -app.MapRazorPages(); - -app.Run("http://localhost:8000"); - -// Note: Set ASPNETCORE_ENVIRONMENT=Development for detailed error pages +host.Run(); diff --git a/PlanTempus.Application/Startup.cs b/PlanTempus.Application/Startup.cs new file mode 100644 index 0000000..06f1cd6 --- /dev/null +++ b/PlanTempus.Application/Startup.cs @@ -0,0 +1,93 @@ +using Autofac; +using PlanTempus.Application.Features.Localization.Services; +using PlanTempus.Application.Features.Menu.Services; +using PlanTempus.Components.ModuleRegistry; +using PlanTempus.Components.Outbox; +using PlanTempus.Core.Configurations.JsonConfigProvider; +using PlanTempus.Core.Configurations; +using PlanTempus.Core.Email; +using PlanTempus.Core.ModuleRegistry; +using PlanTempus.Core.Outbox; + +namespace PlanTempus.Application; + +public class Startup +{ + public Startup(IWebHostEnvironment env) + { + var builder = new Core.Configurations.ConfigurationBuilder() + .AddJsonFile("appconfiguration.json", optional: true, reloadOnChange: true); + + ConfigurationRoot = builder.Build(); + } + + public Core.Configurations.IConfigurationRoot ConfigurationRoot { get; private set; } + + public ILifetimeScope? AutofacContainer { get; private set; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + services.AddOptions(); + + // Add Razor Pages with feature-based structure + services.AddRazorPages(options => + { + options.RootDirectory = "/Features"; + }) + .AddRazorOptions(options => + { + options.ViewLocationFormats.Add("/Features/_Shared/Pages/{0}.cshtml"); + options.ViewLocationFormats.Add("/Features/_Shared/Components/{1}/{0}.cshtml"); + }); + + services.AddAntiforgery(x => x.HeaderName = "X-ANTI-FORGERY-TOKEN"); + } + + public void ConfigureContainer(ContainerBuilder builder) + { + // Application services + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + + // Infrastructure modules + builder.RegisterModule(new Database.ModuleRegistry.DbPostgreSqlModule + { + ConnectionString = ConfigurationRoot.GetConnectionString("DefaultConnection") + }); + + builder.RegisterModule(new TelemetryModule + { + TelemetryConfig = ConfigurationRoot.GetSection("ApplicationInsights").ToObject() + }); + + builder.RegisterModule(); + builder.RegisterModule(); + builder.RegisterModule(); + builder.RegisterModule(new EmailModule + { + PostmarkConfiguration = ConfigurationRoot.GetSection("Postmark").ToObject() + }); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + app.UseDeveloperExceptionPage(); + else + { + app.UseExceptionHandler("/Error"); + app.UseHsts(); + } + + app.UseHttpsRedirection(); + app.UseRouting(); + app.UseStaticFiles(); + + app.UseEndpoints(endpoints => + { + endpoints.MapRazorPages(); + endpoints.MapControllers(); + }); + } +} diff --git a/PlanTempus.Application/appconfiguration.json b/PlanTempus.Application/appconfiguration.json new file mode 100644 index 0000000..9665985 --- /dev/null +++ b/PlanTempus.Application/appconfiguration.json @@ -0,0 +1,19 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Host=192.168.1.63;Port=5432;Database=ptmain;User Id={usr};Password={pwd};" + }, + "ApplicationInsights": { + "ConnectionString": "InstrumentationKey=07d2a2b9-5e8e-4924-836e-264f8438f6c5;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=56748c39-2fa3-4880-a1e2-24068e791548", + "UseSeqLoggingTelemetryChannel": true + }, + "SeqConfiguration": { + "IngestionEndpoint": "http://localhost:5341", + "ApiKey": null, + "Environment": "Development" + }, + "Postmark": { + "ServerToken": "3f285ee7-1d30-48fb-ab6f-a6ae92a843e7", + "FromEmail": "janus@sevenweirdpeople.io", + "TestToEmail": "janus@sevenweirdpeople.io" + } +} diff --git a/PlanTempus.Components/Outbox/OutboxListenerModule.cs b/PlanTempus.Components/Outbox/OutboxListenerModule.cs index 1d5449e..dfb74f2 100644 --- a/PlanTempus.Components/Outbox/OutboxListenerModule.cs +++ b/PlanTempus.Components/Outbox/OutboxListenerModule.cs @@ -1,5 +1,6 @@ using Autofac; using Microsoft.Extensions.Hosting; +using PlanTempus.Core.Telemetry; namespace PlanTempus.Components.Outbox; @@ -7,6 +8,10 @@ public class OutboxListenerModule : Module { protected override void Load(ContainerBuilder builder) { + builder.RegisterType() + .As>() + .SingleInstance(); + builder.RegisterType() .As() .SingleInstance();