diff --git a/EssentialCSharp.Web/Program.cs b/EssentialCSharp.Web/Program.cs index 10d524ec..4b262466 100644 --- a/EssentialCSharp.Web/Program.cs +++ b/EssentialCSharp.Web/Program.cs @@ -1,23 +1,23 @@ -using Azure.Monitor.OpenTelemetry.AspNetCore; -using EssentialCSharp.Web.Areas.Identity.Data; -using EssentialCSharp.Web.Areas.Identity.Services.PasswordValidators; -using EssentialCSharp.Web.Data; -using EssentialCSharp.Web.Extensions; -using EssentialCSharp.Web.Middleware; -using EssentialCSharp.Web.Services; -using EssentialCSharp.Web.Services.Referrals; +using Azure.Monitor.OpenTelemetry.AspNetCore; +using EssentialCSharp.Web.Areas.Identity.Data; +using EssentialCSharp.Web.Areas.Identity.Services.PasswordValidators; +using EssentialCSharp.Web.Data; +using EssentialCSharp.Web.Extensions; +using EssentialCSharp.Web.Middleware; +using EssentialCSharp.Web.Services; +using EssentialCSharp.Web.Services.Referrals; using Mailjet.Client; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.UI.Services; -using Microsoft.EntityFrameworkCore; - -namespace EssentialCSharp.Web; - -public partial class Program -{ - private static void Main(string[] args) - { +using Microsoft.AspNetCore.Identity.UI.Services; +using Microsoft.EntityFrameworkCore; + +namespace EssentialCSharp.Web; + +public partial class Program +{ + private static void Main(string[] args) + { WebApplicationBuilder builder = WebApplication.CreateBuilder(args); builder.Services.Configure(options => @@ -31,20 +31,35 @@ private static void Main(string[] args) options.KnownNetworks.Clear(); options.KnownProxies.Clear(); }); - - ConfigurationManager configuration = builder.Configuration; + + ConfigurationManager configuration = builder.Configuration; string connectionString = builder.Configuration.GetConnectionString("EssentialCSharpWebContextConnection") ?? throw new InvalidOperationException("Connection string 'EssentialCSharpWebContextConnection' not found."); - builder.Logging.AddConsole(); - builder.Services.AddHealthChecks(); + builder.Logging.AddConsole(); + builder.Services.AddHealthChecks(); + + // Create a temporary logger for startup logging + using var loggerFactory = LoggerFactory.Create(loggingBuilder => + loggingBuilder.AddConsole().SetMinimumLevel(LogLevel.Information)); + var logger = loggerFactory.CreateLogger(); if (!builder.Environment.IsDevelopment()) { - // Configure Azure Application Insights with OpenTelemetry - builder.Services.AddOpenTelemetry().UseAzureMonitor(); - builder.Services.AddApplicationInsightsTelemetry(); - builder.Services.AddServiceProfiler(); - } + // Configure Azure Application Insights with OpenTelemetry only if connection string is available + var appInsightsConnectionString = builder.Configuration.GetConnectionString("ApplicationInsights") + ?? builder.Configuration["ApplicationInsights:ConnectionString"]; + + if (!string.IsNullOrEmpty(appInsightsConnectionString)) + { + builder.Services.AddOpenTelemetry().UseAzureMonitor(); + builder.Services.AddApplicationInsightsTelemetry(); + builder.Services.AddServiceProfiler(); + } + else + { + logger.LogWarning("Application Insights connection string not found. Telemetry collection will be disabled."); + } + } builder.Services.AddDbContext(options => options.UseSqlServer(connectionString)); builder.Services.AddDefaultIdentity(options => @@ -70,9 +85,9 @@ private static void Main(string[] args) .AddEntityFrameworkStores() .AddPasswordValidator>() .AddPasswordValidator>(); - - builder.Configuration - .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + + builder.Configuration + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddEnvironmentVariables(); builder.Services.ConfigureApplicationCookie(options => @@ -113,22 +128,22 @@ private static void Main(string[] args) return userPasswordStore; } throw new NotSupportedException("The default UI requires a user store with password support."); - }); + }); - //TODO: Implement the anti-forgery token with every POST/PUT request: https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery + //TODO: Implement the anti-forgery token with every POST/PUT request: https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery if (!builder.Environment.IsDevelopment()) { builder.Services.AddTransient(); } builder.Services.Configure(builder.Configuration.GetSection(AuthMessageSenderOptions.AuthMessageSender)); - - // Add services to the container. + + // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddCaptchaService(builder.Configuration.GetSection(CaptchaOptions.CaptchaSender)); builder.Services.AddSingleton(); builder.Services.AddHostedService(); - builder.Services.AddScoped(); + builder.Services.AddScoped(); if (!builder.Environment.IsDevelopment()) { @@ -161,11 +176,12 @@ private static void Main(string[] args) } - + WebApplication app = builder.Build(); - // Configure the HTTP request pipeline. - if (!app.Environment.IsDevelopment()) - { + + // Configure the HTTP request pipeline. + if (!app.Environment.IsDevelopment()) + { app.UseExceptionHandler("/Error"); app.UseForwardedHeaders(); app.UseHsts(); @@ -176,25 +192,25 @@ private static void Main(string[] args) { app.UseDeveloperExceptionPage(); app.UseForwardedHeaders(); - } + } app.MapHealthChecks("/healthz"); - - app.UseHttpsRedirection(); - app.UseStaticFiles(); - + + app.UseHttpsRedirection(); + app.UseStaticFiles(); + app.UseRouting(); - app.UseAuthentication(); + app.UseAuthentication(); app.UseAuthorization(); app.UseMiddleware(); - - - app.MapRazorPages(); + + + app.MapRazorPages(); app.MapDefaultControllerRoute(); - app.MapFallbackToController("Index", "Home"); - - app.Run(); + app.MapFallbackToController("Index", "Home"); + + app.Run(); } -} +}