Add Publish & Deployment Guide to README.md
Added a detailed "Publish & Deployment Guide" to the README for the `EnvelopeGenerator.Server` project. The guide includes: - Table of contents for easy navigation. - Explanation of differences between `EnvelopeGenerator.Server` and a standard ASP.NET Core API. - Justification for self-contained publishing and its benefits. - Recommended `dotnet publish` command with parameter explanations. - IIS configuration steps, including Application Pool settings, `web.config` adjustments, and module requirements. - Verification checklist for published output files. - Instructions for setting up logging and recycling the IIS Application Pool. - Directory structure overview post-publish. - Troubleshooting common deployment errors with solutions. This guide ensures developers and administrators can successfully publish and deploy the application.
This commit is contained in:
225
EnvelopeGenerator.Server/EnvelopeGenerator.Server/README.md
Normal file
225
EnvelopeGenerator.Server/EnvelopeGenerator.Server/README.md
Normal file
@@ -0,0 +1,225 @@
|
||||
# EnvelopeGenerator.Server — Publish & Deployment Guide
|
||||
|
||||
## Inhaltsverzeichnis
|
||||
|
||||
1. [Unterschied zu einer normalen ASP.NET Core API](#unterschied-zu-einer-normalen-aspnet-core-api)
|
||||
2. [Warum Self-Contained Publish?](#warum-self-contained-publish)
|
||||
3. [Publish-Befehl (Terminal)](#publish-befehl-terminal)
|
||||
4. [IIS-Konfiguration](#iis-konfiguration)
|
||||
5. [Verzeichnisstruktur nach dem Publish](#verzeichnisstruktur-nach-dem-publish)
|
||||
6. [Häufige Fehler](#häufige-fehler)
|
||||
|
||||
---
|
||||
|
||||
## Unterschied zu einer normalen ASP.NET Core API
|
||||
|
||||
`EnvelopeGenerator.Server` ist **keine** gewöhnliche ASP.NET Core Web API. Es handelt sich um eine **Blazor Auto (Server + WebAssembly Hybrid)**-Anwendung.
|
||||
|
||||
| Merkmal | Normale ASP.NET Core API | EnvelopeGenerator.Server (Blazor Auto) |
|
||||
|---|---|---|
|
||||
| Projekttyp | `Microsoft.NET.Sdk.Web` | `Microsoft.NET.Sdk.Web` + WASM Client |
|
||||
| Frontend | Keins / Razor Pages | Blazor Server + Blazor WASM |
|
||||
| WASM-Komponente | Nein | Ja (`EnvelopeGenerator.Server.Client`) |
|
||||
| Framework-DLL-Bindung | Tolerant gegenüber Runtime-Versionen | **Strikt**: WASM erwartet exakte Assembly-Versionen |
|
||||
| Publish ohne .NET auf Zielserver | Nicht nötig (FDD reicht meist) | **Self-Contained Pflicht** empfohlen |
|
||||
| IIS Application Pool | `.NET CLR v4.0` oder `No Managed Code` | **Zwingend: `No Managed Code`** |
|
||||
| Publish-Paketgröße | ~5–20 MB | **~500 MB** (enthält .NET Runtime) |
|
||||
| `web.config processPath` | `dotnet` + `.dll` | **`.\EnvelopeGenerator.Server.exe`** |
|
||||
|
||||
### Warum die WASM-Komponente den Unterschied macht
|
||||
|
||||
Die WASM-Seite der Anwendung (`EnvelopeGenerator.Server.Client`) bindet Assemblies wie
|
||||
`Microsoft.Extensions.DependencyInjection.Abstractions` in einer **fest definierten Version**.
|
||||
Bei einem **Framework-Dependent Deployment** werden diese Assemblies nicht mitgeliefert und
|
||||
müssen auf dem Zielserver vorhanden sein — in der exakt passenden Version.
|
||||
|
||||
Fehlt die passende .NET-Runtime auf dem Zielserver, erscheint folgender Fehler beim Start:
|
||||
|
||||
```
|
||||
Unhandled exception. System.IO.FileNotFoundException:
|
||||
Could not load file or assembly
|
||||
'Microsoft.Extensions.DependencyInjection.Abstractions, Version=8.0.0.0'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Warum Self-Contained Publish?
|
||||
|
||||
Beim **Self-Contained Deployment** werden **alle benötigten .NET Runtime-DLLs** in das
|
||||
Ausgabeverzeichnis kopiert. Die Anwendung ist damit vollständig unabhängig von der auf dem
|
||||
Zielserver installierten .NET-Version.
|
||||
|
||||
| | Framework-Dependent | Self-Contained |
|
||||
|---|---|---|
|
||||
| .NET auf Zielserver nötig | Ja | **Nein** |
|
||||
| Paketgröße | ~20 MB | ~500 MB |
|
||||
| `runtimeconfig.json` | `frameworkVersion` vorhanden | `includedFrameworks` (Runtime eingebettet) |
|
||||
| Fehleranfälligkeit auf Fremd-PC | Hoch | Minimal |
|
||||
|
||||
---
|
||||
|
||||
## Publish-Befehl (Terminal)
|
||||
|
||||
### Empfohlener Befehl (Self-Contained, win-x64)
|
||||
|
||||
```bat
|
||||
dotnet publish EnvelopeGenerator.Server\EnvelopeGenerator.Server\EnvelopeGenerator.Server.csproj ^
|
||||
-c Release ^
|
||||
-f net8.0 ^
|
||||
--self-contained true ^
|
||||
--runtime win-x64 ^
|
||||
-o .\publish-output
|
||||
```
|
||||
|
||||
> Dieser Befehl muss vom **Solution-Root-Verzeichnis** aus ausgefuehrt werden.
|
||||
> Alternativ: `publish.bat` im selben Verzeichnis wie diese README ausfuehren.
|
||||
|
||||
### Parameter-Erklaerung
|
||||
|
||||
| Parameter | Bedeutung |
|
||||
|---|---|
|
||||
| `-c Release` | Release-Konfiguration (optimiert, kein Debug-Code) |
|
||||
| `-f net8.0` | Ziel-Framework explizit angeben (Pflicht, da `<TargetFrameworks>` mehrere Werte haben kann) |
|
||||
| `--self-contained true` | Alle .NET Runtime-DLLs ins Ausgabeverzeichnis kopieren |
|
||||
| `--runtime win-x64` | Zielplattform: Windows 64-Bit |
|
||||
| `-o .\publish-output` | Ausgabeverzeichnis |
|
||||
|
||||
### Doğrulama nach dem Publish
|
||||
|
||||
Nach erfolgreichem Publish folgende Dateien im Ausgabeverzeichnis prüfen:
|
||||
|
||||
```powershell
|
||||
# Diese Dateien MÜSSEN vorhanden sein (Self-Contained-Nachweis):
|
||||
Test-Path ".\publish-output\hostfxr.dll" # .NET Host
|
||||
Test-Path ".\publish-output\coreclr.dll" # .NET Core Runtime
|
||||
Test-Path ".\publish-output\Microsoft.Extensions.DependencyInjection.Abstractions.dll"
|
||||
Test-Path ".\publish-output\EnvelopeGenerator.Server.exe"
|
||||
Test-Path ".\publish-output\web.config"
|
||||
```
|
||||
|
||||
Alle Ergebnisse müssen `True` sein.
|
||||
|
||||
---
|
||||
|
||||
## IIS-Konfiguration
|
||||
|
||||
> **WICHTIG:** Diese Einstellungen unterscheiden sich von einer normalen ASP.NET Core API
|
||||
> und sind zwingend erforderlich.
|
||||
|
||||
### 1. Application Pool — `No Managed Code`
|
||||
|
||||
ASP.NET Core (und damit auch Blazor) verwaltet seinen eigenen Runtime-Lifecycle.
|
||||
IIS darf **keinen** .NET CLR-Managed-Code-Kontext aktivieren.
|
||||
|
||||
**Einstellung:**
|
||||
|
||||
```
|
||||
IIS Manager
|
||||
→ Application Pools
|
||||
→ [Pool-Name der Anwendung] → Basic Settings
|
||||
→ .NET CLR Version: "No Managed Code" ← ZWINGEND
|
||||
```
|
||||
|
||||
> **Fehler bei falscher Einstellung:** HTTP 500.30 — ASP.NET Core app failed to start
|
||||
> (sc-win32-status: 574 in IIS-Logs)
|
||||
|
||||
### 2. ASP.NET Core Module V2
|
||||
|
||||
Das IIS-Modul `AspNetCoreModuleV2` muss installiert sein.
|
||||
Es wird über das **.NET Hosting Bundle** mitgeliefert.
|
||||
|
||||
Prüfen:
|
||||
```
|
||||
IIS Manager → Modules → "AspNetCoreModuleV2" vorhanden?
|
||||
```
|
||||
|
||||
Falls nicht installiert: [.NET 8 Hosting Bundle herunterladen](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
|
||||
und nach der Installation IIS neu starten:
|
||||
|
||||
```cmd
|
||||
net stop was /y && net start w3svc
|
||||
```
|
||||
|
||||
### 3. web.config — Korrekte Konfiguration für Self-Contained
|
||||
|
||||
Nach dem Publish wird `web.config` automatisch generiert. Für Self-Contained muss sie so aussehen:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<location path="." inheritInChildApplications="false">
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*"
|
||||
modules="AspNetCoreModuleV2" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<aspNetCore processPath=".\EnvelopeGenerator.Server.exe"
|
||||
stdoutLogEnabled="false"
|
||||
stdoutLogFile=".\logs\stdout"
|
||||
hostingModel="inprocess" />
|
||||
</system.webServer>
|
||||
</location>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
**Kritische Unterschiede zu Framework-Dependent:**
|
||||
|
||||
| Eigenschaft | Framework-Dependent (FALSCH) | Self-Contained (RICHTIG) |
|
||||
|---|---|---|
|
||||
| `processPath` | `dotnet` | `.\EnvelopeGenerator.Server.exe` |
|
||||
| `arguments` | `.\EnvelopeGenerator.Server.dll` | *(leer oder weggelassen)* |
|
||||
|
||||
### 4. Berechtigungen für das `logs`-Verzeichnis
|
||||
|
||||
Wenn `stdoutLogEnabled="true"` gesetzt wird (zur Fehlerdiagnose), muss das `logs`-Verzeichnis
|
||||
existieren und der IIS-Prozess muss Schreibrechte haben:
|
||||
|
||||
```powershell
|
||||
New-Item -ItemType Directory -Path "C:\inetpub\wwwroot\<App-Pfad>\logs" -Force
|
||||
icacls "C:\inetpub\wwwroot\<App-Pfad>\logs" /grant "IIS_IUSRS:(OI)(CI)F"
|
||||
```
|
||||
|
||||
> Ohne dieses Verzeichnis kann die Anwendung bei aktiviertem Logging **nicht starten**.
|
||||
|
||||
### 5. Application Pool Recycle nach Deployment
|
||||
|
||||
Nach jedem Deployment den Application Pool neu starten:
|
||||
|
||||
```cmd
|
||||
# IIS Manager → Application Pools → [Pool] → Recycle
|
||||
# oder per Kommandozeile (als Administrator):
|
||||
%windir%\system32\inetsrv\appcmd recycle apppool /apppool.name:"<Pool-Name>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verzeichnisstruktur nach dem Publish
|
||||
|
||||
```
|
||||
publish-output\
|
||||
├── EnvelopeGenerator.Server.exe ← Startpunkt (Self-Contained)
|
||||
├── EnvelopeGenerator.Server.dll ← Managed Assembly
|
||||
├── EnvelopeGenerator.Server.runtimeconfig.json
|
||||
├── EnvelopeGenerator.Server.deps.json
|
||||
├── web.config ← IIS-Konfiguration (auto-generiert)
|
||||
├── hostfxr.dll ← .NET Host (Self-Contained-Nachweis)
|
||||
├── coreclr.dll ← .NET Core Runtime
|
||||
├── Microsoft.Extensions.*.dll ← Framework-DLLs (jetzt enthalten!)
|
||||
├── DevExpress.*.dll ← UI-Komponenten
|
||||
├── wwwroot\ ← Statische Web-Assets
|
||||
│ ├── _framework\ ← WASM-Binaries
|
||||
│ └── ...
|
||||
└── logs\ ← Stdout-Logs (manuell anlegen!)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Häufige Fehler
|
||||
|
||||
| Fehler | Ursache | Lösung |
|
||||
|---|---|---|
|
||||
| `FileNotFoundException: Microsoft.Extensions.DependencyInjection.Abstractions` | Framework-Dependent Publish auf Server ohne .NET 8 | Self-Contained Publish verwenden |
|
||||
| `HTTP 500.30` in IIS | App startet nicht | Application Pool auf `No Managed Code` setzen |
|
||||
| `HTTP 500.30` + `sc-win32-status: 574` | App Pool falsch oder `AspNetCoreModuleV2` fehlt | Pool prüfen + Hosting Bundle installieren |
|
||||
| App startet per `.exe`, aber nicht in IIS | `web.config` hat noch `processPath="dotnet"` | `web.config` auf `.\EnvelopeGenerator.Server.exe` korrigieren |
|
||||
| Logs-Verzeichnis fehlt → App startet nicht | `stdoutLogEnabled="true"` aber `logs\` existiert nicht | `logs\`-Ordner anlegen + IIS_IUSRS Schreibrecht geben |
|
||||
Reference in New Issue
Block a user