Fix blazor.web.js 404: move App.razor and Routes.razor to Host project

Root cause: App.razor was in CentralUI (Microsoft.NET.Sdk.Razor RCL) but
MapRazorComponents<App>().AddInteractiveServerRenderMode() serves
_framework/blazor.web.js from the host assembly (Microsoft.NET.Sdk.Web).
Per MS docs, the root component must be in the server (host) project.

- Move App.razor and Routes.razor from CentralUI to Host/Components/
- Add Host/_Imports.razor for Razor component usings
- Make MapCentralUI generic: MapCentralUI<TApp>() accepts root component
- Add AdditionalAssemblies to discover CentralUI's pages/layouts
- Routes.razor references both Host and CentralUI assemblies
- Fix all DI registrations (TemplateEngine services)
- SCADALINK_CONFIG env var for role-specific config loading

Verified: blazor.web.js HTTP 200 (200KB), login page renders with Blazor
interactive server mode, SignalR circuit establishes, LDAP auth works.
This commit is contained in:
Joseph Doherty
2026-03-17 04:01:12 -04:00
parent 0b10747bd2
commit 6fa4c101ab
9 changed files with 788 additions and 52 deletions

View File

@@ -20,9 +20,15 @@ using ScadaLink.StoreAndForward;
using ScadaLink.TemplateEngine;
using Serilog;
// SCADALINK_CONFIG determines which role-specific config to load (Central or Site)
// DOTNET_ENVIRONMENT/ASPNETCORE_ENVIRONMENT stay as "Development" for dev tooling (static assets, EF migrations, etc.)
var scadalinkConfig = Environment.GetEnvironmentVariable("SCADALINK_CONFIG")
?? Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT")
?? "Production";
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddJsonFile($"appsettings.{scadalinkConfig}.json", optional: true)
.AddEnvironmentVariables()
.AddCommandLine(args)
.Build();
@@ -110,6 +116,8 @@ try
// Middleware pipeline
app.UseStaticFiles();
app.UseWebSockets();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseAntiforgery();
@@ -120,7 +128,7 @@ try
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
app.MapCentralUI();
app.MapCentralUI<ScadaLink.Host.Components.App>();
app.MapInboundAPI();
await app.RunAsync();
}