diff --git a/timetracker.db b/timetracker.db index 720ffe9..5ed71f7 100644 Binary files a/timetracker.db and b/timetracker.db differ diff --git a/wasm.md b/wasm.md new file mode 100644 index 0000000..68bc983 --- /dev/null +++ b/wasm.md @@ -0,0 +1,183 @@ +# Blazor WASM Migration – Aufwandsanalyse + +> Analysiert am 08.06.2026 +> Aktueller Stack: Blazor Server (.NET 10, InteractiveServer, SQLite, MudBlazor 9.4) + +--- + +## TL;DR + +Eine vollständige Migration auf Blazor WebAssembly ist **technisch möglich**, aber ein **erheblicher Umbau**. Der Aufwand liegt bei schätzungsweise **3–5 Wochen** für einen Entwickler. Der Hauptgrund: Blazor WASM läuft vollständig im Browser – kein direkter DB-Zugriff, keine Cookie-Auth serverseitig, keine gemeinsamen In-Process-Events zwischen Nutzern. + +**Empfehlung:** Hybrid-Modell (Blazor Auto oder WASM + ASP.NET Core API auf demselben Server) ist der pragmatischste Weg. + +--- + +## Was WASM bringt + +| Vorteil | Erklärung | +|---|---| +| Keine SignalR-Verbindung nötig | WASM lädt den Code einmalig herunter, kein dauerhafter WebSocket | +| Besser skalierbar | Server hält keine Circuits pro User im Speicher | +| Offline-fähig (theoretisch) | Progressive Web App möglich | +| Geringere Serverauslastung | UI-Logik läuft im Browser | + +**Aber Achtung:** Der initiale Download ist größer (~10–20 MB .NET Runtime im Browser), erste Ladezeit spürbar langsamer als Blazor Server. + +--- + +## Aktuelle Blocker (nach Schwere) + +### 🔴 KRITISCH – muss komplett umgebaut werden + +#### 1. Datenbankzugriff – EF Core / SQLite + +Alle drei Services greifen direkt per `IDbContextFactory` auf die SQLite-DB zu: + +- `AuthService` → Login, Registrierung, User-CRUD +- `TimetrackerService` → Arbeitstage, Pausen, Einstellungen, Urlaub, Überstunden +- `HolidayService` → Feiertage speichern/lesen + +**WASM kann nicht direkt auf eine Datenbank zugreifen.** Browser hat keinen Dateisystemzugriff. + +→ **Lösung:** Alle Service-Methoden als REST-API-Endpoints auf dem Server exponieren. WASM-Client ruft diese per `HttpClient` auf. + +**Aufwand:** ~10–15 Tage (je nach gewähltem API-Stil: Minimal API vs. Controller) + +--- + +#### 2. Cookie-Authentifizierung + +Aktuell läuft der gesamte Auth-Flow serverseitig: +- `POST /auth/login` → `HttpContext.SignInAsync()` → Cookie setzen +- `GET /auth/logout` → `HttpContext.SignOutAsync()` +- Blazor-Komponenten lesen den Cookie über `CascadingAuthenticationState` + +In WASM gibt es keinen direkten Zugriff auf `HttpContext`. Die Cookie-Auth muss weiterhin **serverseitig** verbleiben, aber das Login-Formular muss über die API kommunizieren. + +→ **Lösung A (einfacher):** Cookie-Auth beibehalten, aber Login-Formular als API-Call (kein HTML-Form-Post mehr). WASM erhält Auth-State über einen `/auth/me`-Endpoint. +→ **Lösung B (aufwändiger):** JWT-Token-Auth einführen, Token im Browser-Speicher halten. + +**Empfehlung:** Lösung A, da Cookie-Auth bereits implementiert ist und sicherer gegen XSS ist als localStorage-JWTs. + +**Aufwand:** ~3–4 Tage + +--- + +#### 3. Projektstruktur – neue Build-Konfiguration + +Aktuell: 1 Projekt (`Microsoft.NET.Sdk.Web`), alles in einem. + +WASM benötigt mindestens: +- **`timetracker.Client`** – Blazor WASM-Projekt (läuft im Browser) +- **`timetracker.Server`** – ASP.NET Core-Projekt (hostet API + WASM-App) +- Optional: **`timetracker.Shared`** – DTOs/Models geteilt zwischen Client & Server + +Alle `@inject`-Direktiven, die auf Server-Services zeigen, müssen im Client auf `HttpClient`-basierte Services umgestellt werden. + +**Aufwand:** ~3–4 Tage (Projektaufspaltung, DI-Umverdrahtung) + +--- + +### ⚠️ MITTEL – umbaubar, aber aufwändig + +#### 4. UserNotificationService (Live-Updates) + +Aktuell: Singleton mit C#-Events, der zwischen Blazor Server-Circuits kommuniziert: +- Admin löscht User → Event feuert → alle aktiven `MainLayout`-Instanzen reagieren +- Neuer User registriert → `AdminUsers` aktualisiert sich live + +In WASM gibt es keine gemeinsamen In-Process-Events. Jeder Browser ist isoliert. + +→ **Lösung:** **SignalR Hub** einführen. Server sendet Push-Nachrichten an alle verbundenen Clients. + +``` +[Browser A – Admin] [Server] [Browser B – normaler User] + löscht User C → Hub.Clients.All.SendAsync → empfängt "UserDeleted(C)" + → NavigateTo("/auth/logout") +``` + +**Aufwand:** ~2–3 Tage (Hub einrichten, Client-seitig `HubConnection` einbauen) + +--- + +#### 5. Formular-basiertes Login/Register + +Login und Registrierung verwenden aktuell native HTML-Forms (`method="post"`) die direkt an `/auth/login` und `/auth/register` posten. Das funktioniert in WASM nicht mehr sauber, weil WASM SPA-Navigation nutzt. + +→ **Lösung:** Login-Formular auf `@code`-basierten `HttpClient.PostAsync`-Call umstellen, Redirect über `NavigationManager`. + +**Aufwand:** ~1 Tag + +--- + +#### 6. Docker-Deployment + +Aktuell: 1 Container, alles drin. + +WASM + API = zwei Artefakte: +- Die WASM-App sind statische Dateien (HTML/JS/WASM) +- Die API läuft als ASP.NET Core-Server + +→ **Lösung A (einfach):** Hosted WASM – API-Server liefert auch die WASM-Dateien aus (1 Container, 1 Dockerfile, wie heute) +→ **Lösung B (komplex):** Getrennte Container (Nginx für WASM, API separat) + +**Empfehlung:** Lösung A (Hosted WASM) – minimaler Deployment-Overhead. + +**Aufwand:** ~0,5 Tage bei Lösung A + +--- + +### ✅ KEIN UMBAU NÖTIG + +| Komponente | Warum kein Umbau | +|---|---| +| **MudBlazor 9.4** | Vollständig WASM-kompatibel | +| **Alle `.razor`-Seiten (UI)** | Markup bleibt identisch, nur `@inject` ändert sich | +| **Entity Models** (User, WorkDay, etc.) | Können ins Shared-Projekt verschoben werden | +| **HttpClient für Feiertage** (nager.at) | Funktioniert in WASM nativ | +| **Business-Logik in Komponenten** | Bleibt unverändert | +| **CSS / MudBlazor Theme** | Unverändert | + +--- + +## Gesamtaufwand-Schätzung + +| Aufgabe | Geschätzter Aufwand | +|---|---| +| Projektstruktur aufteilen (Client/Server/Shared) | 2–3 Tage | +| REST-API für TimetrackerService | 4–5 Tage | +| REST-API für AuthService + HolidayService | 2–3 Tage | +| Cookie-Auth auf API-Flow umstellen | 2–3 Tage | +| Client-Services (HttpClient-basiert) erstellen | 3–4 Tage | +| SignalR für Live-Notifications | 2–3 Tage | +| Login/Register-Formulare anpassen | 1 Tag | +| Docker/Deployment anpassen | 0,5–1 Tag | +| Testen & Debugging | 2–3 Tage | +| **Gesamt** | **~18–26 Tage** | + +--- + +## Empfohlene Alternative: Blazor Auto + +.NET 8+ bietet **Blazor Auto**-Rendermodus: Seiten starten als Server-Rendering, wechseln dann automatisch zu WASM sobald die Runtime heruntergeladen ist. Das gibt sofortige Interaktivität (Server) + langfristig WASM-Performance. + +**Vorteil:** DB-Zugriff und Auth bleiben wie heute, kein API-Layer nötig. +**Aufwand:** ~3–5 Tage (Projektstruktur, Shared-Projekt, WASM-Client-Projekt anlegen). + +**Für dieses Projekt sehr empfehlenswert**, da: +1. Minimaler Umbau der bestehenden Logik +2. Spürbare Performance-Verbesserung nach erstem Laden +3. Kein SignalR-Umbau notwendig (Server-Circuit bleibt beim ersten Laden aktiv) + +--- + +## Fazit + +| Option | Aufwand | Performance-Gewinn | Empfehlung | +|---|---|---|---| +| Blazor WASM (pure) | ~20–25 Tage | Hoch (nach erstem Laden) | Nur bei hoher Nutzerzahl sinnvoll | +| Blazor Auto | ~3–5 Tage | Mittel-Hoch | ✅ **Empfohlen** | +| Blazor Server (wie heute) | 0 | – | Gut für kleine Nutzerzahl | + +Für den aktuellen Use-Case (internes Uni-Tool, überschaubare Nutzerzahl) ist **Blazor Auto** das beste Kosten-Nutzen-Verhältnis. Eine vollständige WASM-Migration lohnt sich erst, wenn die App deutlich mehr parallele User hat oder offline-Fähigkeit gefordert wird.