Switch Blazor-Interaktivität
Das Umschalten eines bestehenden Power Portals Pro-Projekts von einem Interaktivitätsmodus in einen anderen erfolgt durch eine Reihe von Änderungen an Program.cs, App.razor, dem .Client Projekt und (beim Hinzufügen von Interaktivität) den Kontoseiten. Das Framework selbst benötigt keine Änderungen – nur die Host-Verkabelung schon. Die folgenden Schritte behandeln die gängigen Übergänge.
Tipp
Wenn deine Anpassungen auf wenigen Seiten liegen, ist der geringste Weg ein neues Projekt im Zielmodus zu unterstützen und deine Anpassungen zu kopieren. Der Vergleich deines aktuellen Hosts mit einer frisch generierten Referenz ist ebenfalls hilfreich, wenn du nach einem manuellen Wechsel einer Diskrepanz nachgehen möchtest.
dotnet new powerportalspro -o MyPortal-Reference --interactivity Auto
Server → WebAssembly oder Auto
Diese Schritte fügen WebAssembly zu einem Server-only-Host hinzu. Die gleichen Bearbeitungen gelten, egal ob du nur WebAssembly oder Auto anvisierst – die einzigen Unterschiede sind, welche Builder-Methoden du verkettest Program.cs und welcher Rendermodus App.razor zurückkehrt. Beide werden pro Schritt aufgerufen.
1. Konvertiere das . Client-Projekt zu einer WebAssembly-App
Öffnen .Client/MyApp.Client.csproj und das SDK von Microsoft.NET.Sdk.Razor . Microsoft.NET.Sdk.BlazorWebAssembly Fügen Sie das WebAssembly-Framework und Power Portals Pro Client-Pakete hinzu:
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" />
<PackageReference Include="PowerPortalsPro.Web.Client" />
<PackageReference Include="PowerPortalsPro.Web.Blazor.FluentUI" />
<PackageReference Include="PowerPortalsPro.Web.Common" />
</ItemGroup>
</Project>
Fügen Sie auch das WebAssembly-Server-Side-Hosting-Paket zum Server-Host .csproj hinzu – es stellt die Middleware bereit, die das WASM-Bundle bedient:
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
2. Interaktive WebAssembly-Komponenten auf dem Server registrieren
Im Server Program.csersetzen Sie die Komponentenregistrierung durch die entsprechenden Builder-Aufrufe. AddAuthenticationStateSerialization() Serialisiert den authentifizierten Benutzer über die Server→WASM-Grenze, sodass die Kaskadierung AuthenticationState auf beiden Laufzeiten konsistent ist:
// Ersetzen
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
// Mit (Auto)
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents()
.AddAuthenticationStateSerialization();
// Oder (WebAssembly)
builder.Services.AddRazorComponents()
.AddInteractiveWebAssemblyComponents()
.AddAuthenticationStateSerialization();
3. Kartiere den WebAssembly-Rendermodus
Aktualisieren app.MapRazorComponents<App>() Sie, um die passenden Rendermodus-Endpunkte zu verknüpfen. Der AddAdditionalAssemblies Aufruf zeigt bereits auf die .Client Assemblys _Imports in den Vorlagen, daher ändert er sich hier nicht:
// Auto
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(MyApp.Client._Imports).Assembly);
// WebAssembly
app.MapRazorComponents<App>()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(MyApp.Client._Imports).Assembly);
4. App.razors PageRenderMode aktualisieren
In App.razor's PageRenderMode Getter kehre der neue Rendermodus zurück. Pinne /Account/* zuerst auf InteractiveWebAssemblyRenderMode(prerender: false)und gib dann für alles andere die Standardeinstellung zurück:
// Im PageRenderMode-Getter von App.razor
if (HttpContext.Request.Path.StartsWithSegments("/Account"))
return new InteractiveWebAssemblyRenderMode(prerender: false);
// Auto
return new InteractiveAutoRenderMode();
// WebAssembly
return new InteractiveWebAssemblyRenderMode();
Der Account-route-Pin ist erforderlich, da der des Frameworks IAuthService nur im DI-Graphen des WASM-Clients registriert ist. Ohne den Pin kann Autos serverseitiges Prerendering in einer Cold Session nicht aufgelöst werden [Inject] IAuthService .
5. Fügen Sie . hinzu. Kunde/Program.cs
Erstelle ein Formular Program.cs im .Client Projekt. Dies richtet den WebAssembly-Host ein, registriert ihn HttpClient beim Cookie-Forwarding-Handler (also authentifizierte Aufrufe vom WASM-Client, um /api/* denselben Authentifizierungscookie wie der Browser zu sehen) und ruft die WASM-seitige Framework-Dienste auf. AddPowerPortalsProWebClient Der UserPowerPortalsProWebClient Aufruf holt beim Start die querschneidenden Lokalisierungsstrings vorab ab, sodass der erste Paint keinen Key-as-Fallback-Text zeigt:
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.FluentUI.AspNetCore.Components;
using PowerPortalsPro.Web.Blazor.FluentUI;
using PowerPortalsPro.Web.Client;
using PowerPortalsPro.Web.Client.Services;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddFluentUIComponents();
builder.Services.AddSingleton<CookieCredentialsHandler>();
builder.Services.AddHttpClient("PowerPortalsPro", client =>
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<CookieCredentialsHandler>();
builder.Services.AddSingleton(sp =>
sp.GetRequiredService<IHttpClientFactory>().CreateClient("PowerPortalsPro"));
builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthenticationStateDeserialization();
builder.Services.AddPowerPortalsProWebClient();
var app = builder.Build();
await app.UserPowerPortalsProWebClient(
LocalizationBaselines.Default.Concat(new[] { "app" }).ToArray());
await app.RunAsync();
6. Wechsel von Formularpost- zu JSON-Auth-Endpunkten
Server-Hosts werden für Formular-Post-Identitätsseiten verwendet MapAdditionalIdentityEndpoints() . WebAssembly- und Auto-Hosts verwenden MapAuthEndpoints<TUser>() stattdessen – der .Client's Wrapper IAuthService ruft diese JSON-Endpunkte unter folgende Worte auf /api/auth/*:
// Füge dem Server Program.cs hinzu (nach App. UsePowerPortalsProWebServer)
app.MapAuthEndpoints<PortalUser>();
// Tausche optional die Form-Post Identity-Endpunkte gegen die JSON-Endpunkte aus
// (lösche die untenstehende Zeile – sie wird nur von server-gerenderten Account-Seiten verbraucht)
// App. MapAdditionalIdentityEndpoints();
Wenn der Host sowohl Server- als auch WASM-Kontoseiten betreibt (ungewöhnlich), können beide Endpunktregistrierungen koexistieren. Die Standard-Templates wählen das eine oder das andere basierend auf dem Interaktivitätsmodus.
7. Verschieben Sie die Kontoseiten auf die . Kundenprojekt
Power Portals Pro liefert zwei parallele Sets von Kontoseiten, eine für jeden Render-Kontext:
- Lösche die servergerenderten Seiten darunter
Components/Account/Pages/und die Hilfsklassen (IdentityRedirectManager,IdentityUserAccessor,IdentityComponentsEndpointRouteBuilderExtensions,CookieLoginController) aus dem Serverprojekt. - Füge die WASM-Kontoseiten unter
.Client/Pages/Account/. hinzu. Der schnellste Weg ist, ein frisches Projekt mit--interactivity Autoeinem Gerüst zu unterstützen und zu kopieren – sie umfassen Login, Registrieren, Passwort vergessen, Passwort zurücksetzen, E-Mail bestätigen, ExternalLogin und das komplette Manage/* Surface. - Wenn du eine der server-gerenderten Account-Seiten (benutzerdefinierte Validierung, zusätzliche Felder) angepasst hast, kannst du diese Anpassungen auf die WASM-Äquivalente übertragen – sie implementieren die gleiche UX
IAuthServicestattUserManager.
8. Optional — scoped exception handler für /api/*
Wenn WebAssembly im Einsatz ist, werden Ausnahmen von /api/* der Notwendigkeit, den WASM-Client als RFC 9457 problem+json zu benutzen, geworfen, damit die Client-Seite PowerPortalsProService den ursprünglichen CLR-Typ rehydratisieren kann. Die Vorlagen verbinden dies mit einem Scoped UseExceptionHandler for /api/* Only — Die Developer Exception Page behandelt weiterhin Server-gerenderte Seitenfehler an anderer Stelle:
if (app.Environment.IsDevelopment())
{
app.UseWebAssemblyDebugging();
app.UseWhen(
ctx => ctx.Request.Path.StartsWithSegments("/api"),
branch => branch.UseExceptionHandler());
}
WebAssembly oder Auto → Server
Kehren Sie die obigen Schritte um:
- Entfernen
AddInteractiveWebAssemblyComponents()undAddAuthenticationStateSerialization()aus der Server-Komponentenregistrierung; nur behaltenAddInteractiveServerComponents(). - Ersetzen
.AddInteractiveWebAssemblyRenderMode()Sie (und alleInteractiveServerRenderModenebengeschalteten) durch einen einzelnen.AddInteractiveServerRenderMode()Ein.MapRazorComponents<App>() - In
App.razor'sPageRenderMode, lass den/Account/*Pin fallen und kehre für jede interaktive Route zurücknew InteractiveServerRenderMode(). - Verschieben Sie die Account-Seiten mit dem
UserManager-direct-Muster zurück zum ServerprojektComponents/Account/Pages/(oder stellen Sie ein neues Serverprojekt ein Scaffold und kopieren Sie es darüber). Füge das Set wieder hinzuIdentityRedirectManager/IdentityUserAccessorentferne es.Client/Pages/Account/wieder. - Ersetzen Sie
app.MapAuthEndpoints<PortalUser>()durchapp.MapAdditionalIdentityEndpoints(). - Ändere das SDK des
.ClientProjekts zurück aufMicrosoft.NET.Sdk.Razor, verlasse die WebAssembly-Paketreferenzen und lösche.Client/Program.csund.Client/wwwroot/.
Auto ↔ WebAssembly
Der günstigste Switch – das Projektlayout, die Pakete und die Account-Seiten – sind zwischen den beiden identisch. Nur drei Dinge ändern sich:
- In
App.razor'sPageRenderModetauschenew InteractiveAutoRenderMode()du gegennew InteractiveWebAssemblyRenderMode()(oder umgekehrt) auf dem Standard-Zweig. Der/Account/*Pin bleibt in beiden Modi gleich. - Im Server
Program.cshinzufügen oder entfernenAddInteractiveServerComponents()AddRazorComponents()– Auto benötigt es, nur WebAssembly nicht. - Im Server
Program.cs, fügen Sie in ein oder entfernen.AddInteractiveServerRenderMode()Sie .MapRazorComponents<App>()
Überprüfung des Schalters
Nach der Vornahme der Änderungen:
- Baue die Lösung. Die meisten Verdrahtungsfehler treten bereits zur Kompilierungszeit auf – fehlende Rendermodus-Methoden, ungelöste Typen oder veraltete Account-Seiten-Referenzen.
- Melden Sie sich an- und aus. Auth ist das Störendste, um zu wechseln – nutzen Sie den vollständigen Anmelde- → Profilverwaltungszyklus → Ausloggen, um sicherzustellen, dass die neuen Endpunkte korrekt verkabelt sind.
- Klicken Sie auf eine interaktive Seite. Ein Knopfklick auf einem Raster oder Editor beweist, dass die Interaktivität die richtige Laufzeit erreicht. Im Servermodus wird eine SignalR-Verbindung im WebSocket-Tab der Entwicklungstools angezeigt; WebAssembly zeigt die Laufzeitdateien unter
/_framework/dem Netzwerk-Tab an. - Überprüfe das WASM-Bundle beim ersten Laden. Für WebAssembly- und Auto-Modi sollte der Netzwerk-Tab bei einem frischen Laden (Inkognito oder gelöschter Cache) die Laufzeit + Framework + Portal-Assemblies anzeigen, die einströmen.
- Verifiziere die Konto-/Verwaltungsseiten. Profiländerungen, Passwortänderungen und externe Login-Verknüpfungen haben jeweils einen anderen Endpunkt – bestätigen Sie, dass sie alle sauber abgeschlossen werden.
Anmerkung
Achten Sie auf Diskrepanzen zwischen der Dienstdauer beim Verschieben von Diensten zwischen Server und WASM-Client. Der WASM-Host läuft pro Sitzung als einzelner Scope, aber die Caching-Dienste des Frameworks sind als Singletons registriert – wenn Sie Ihren eigenen Dienst auf
Transientder WASM-Seite registrieren, setzt der per-Instanz-Zustand jede Auflösung stillschweigend zurück. VerwendenSingletonSie auf der WASM-Seite für jeden Dienst, der einen veränderbaren Zustand hat.
