-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
107 lines (88 loc) · 4.85 KB
/
Program.cs
File metadata and controls
107 lines (88 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using CloudZen;
using CloudZen.Models.Options;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using CloudZen.Services;
using CloudZen.Services.Abstractions;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
// =============================================================================
// LOCAL DEVELOPMENT: API URL OVERRIDE
// =============================================================================
// In production (Azure Static Web Apps), "/api" routes are proxied to the linked
// Azure Functions app automatically. In local development, the Blazor app and the
// Functions API run on separate ports, so API calls must use the absolute URL.
//
// NOTE: appsettings.Development.json can silently fail to load in Blazor WASM
// (the client fetches it via HTTP and skips it on any error). This programmatic
// override is more reliable for local development.
// =============================================================================
if (builder.HostEnvironment.IsDevelopment())
{
const string functionsLocalUrl = "http://localhost:7257/api"; // update with your local Functions URL and port
builder.Configuration["ChatbotService:ApiBaseUrl"] = functionsLocalUrl;
builder.Configuration["EmailService:ApiBaseUrl"] = functionsLocalUrl;
}
// =============================================================================
// CONFIGURATION WITH IOPTIONS PATTERN
// =============================================================================
// The IOptions pattern provides:
// - Strongly-typed access to configuration settings
// - Compile-time checking of configuration access
// - Easy unit testing through mocking
// - Support for configuration validation
//
// Note: Blazor WebAssembly uses BindConfiguration() extension method
// =============================================================================
// Configure Email Service options from appsettings.json
// Section: "EmailService"
builder.Services.AddOptions<EmailServiceOptions>()
.BindConfiguration(EmailServiceOptions.SectionName);
// Configure Blob Storage options from appsettings.json
// Section: "BlobStorage"
builder.Services.AddOptions<BlobStorageOptions>()
.BindConfiguration(BlobStorageOptions.SectionName);
// Configure Chatbot Service options from appsettings.json
// Section: "ChatbotService"
builder.Services.AddOptions<ChatbotOptions>()
.BindConfiguration(ChatbotOptions.SectionName);
// =============================================================================
// HTTP CLIENT REGISTRATION
// =============================================================================
// Register HttpClient with base address for API calls
builder.Services.AddScoped(sp => new HttpClient
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
// =============================================================================
// SECURITY NOTES FOR BLAZOR WEBASSEMBLY
// =============================================================================
// - Blazor WebAssembly cannot use DefaultAzureCredential() - requires secure server environment
// - Cannot access secrets.json directly - use Azure Key Vault via backend API
// - All configuration in wwwroot/appsettings.json is publicly accessible
// - NEVER store API keys, connection strings, or secrets in client-side config
// - Use Azure Functions backend for sensitive operations (email, storage writes)
// =============================================================================
// =============================================================================
// SERVICE REGISTRATIONS
// =============================================================================
// Register GoogleCalendarUrlService
builder.Services.AddScoped<GoogleCalendarUrlService>();
// Register TicketService as the implementation for ITicketService
builder.Services.AddScoped<ITicketService, TicketService>();
// Register ResumeService (uses IOptions<BlobStorageOptions> for configuration)
builder.Services.AddScoped<ResumeService>();
// Register ApiEmailService as the implementation for IEmailService
// Uses IOptions<EmailServiceOptions> for configuration
// This sends emails through the Azure Functions API backend (secure for WebAssembly)
builder.Services.AddScoped<IEmailService, ApiEmailService>();
// Register ChatbotService as the implementation for IChatbotService
// Uses IOptions<ChatbotOptions> for configuration
// This sends chat messages through the Azure Functions API backend (API key stays server-side)
builder.Services.AddScoped<IChatbotService, ChatbotService>();
// Register ProjectService for managing portfolio projects
builder.Services.AddScoped<ProjectService>();
// Register PersonalService for managing service offerings
builder.Services.AddScoped<PersonalService>();
await builder.Build().RunAsync();