Files
EnvelopeGenerator/EnvelopeGenerator.Server/EnvelopeGenerator.Server
TekH 77379265c2 Add dotnet-tools.json and publish script for .NET 8
Added a `dotnet-tools.json` file to define a .NET tool manifest, specifying the `dotnet-ef` tool with version `10.0.9`.

Introduced a `publish.bat` script for publishing the `EnvelopeGenerator.Server` project as a self-contained application targeting `win-x64` and .NET 8. The script handles cleaning, publishing, output verification, and provides deployment instructions for IIS.

Updated the `EnvelopeGenerator.sln` file to include a reference to the `publish.bat` script under the `EnvelopeGenerator.Server` project using a `SolutionItems` section.
2026-07-02 15:53:49 +02:00
..

EnvelopeGenerator.Server — Publish & Deployment Guide

Inhaltsverzeichnis

  1. Unterschied zu einer normalen ASP.NET Core API
  2. Warum Self-Contained Publish?
  3. Publish-Befehl (Terminal)
  4. IIS-Konfiguration
  5. Verzeichnisstruktur nach dem Publish
  6. 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 ~520 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)

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:

# 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 und nach der Installation IIS neu starten:

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 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:

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:

# 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