# Dienstanbieter

Source: https://docs.sisk-framework.org/de/docs/extensions/service-providers.html

Service Providers ist eine Möglichkeit, Ihre Sisk-Anwendung in verschiedene Umgebungen zu portieren, indem Sie eine portable Konfigurationsdatei verwenden. Diese Funktion ermöglicht es Ihnen, den Port des Servers, Parameter und andere Optionen zu ändern, ohne den Anwendungscode für jede Umgebung anpassen zu müssen. Dieses Modul hängt von der Sisk‑Bausyntax ab und kann über die UsePortableConfiguration‑Methode konfiguriert werden.

Ein Konfigurationsanbieter wird mit `IConfigurationProvider` implementiert, das einen Konfigurationsleser bereitstellt und jede Implementierung erhalten kann. Standardmäßig liefert Sisk einen JSON‑Konfigurationsleser, es gibt jedoch auch ein Paket für INI‑Dateien. Sie können auch Ihren eigenen Konfigurationsanbieter erstellen und ihn registrieren mit:

```csharp
using var app = HttpServer.CreateBuilder()
    .UsePortableConfiguration(config =>
    {
        config.WithConfigReader<MyConfigurationReader>();
    })
    .Build();
```

Wie bereits erwähnt, ist der Standardanbieter eine JSON‑Datei. Standardmäßig wird nach der Datei `service-config.json` gesucht, und zwar im aktuellen Verzeichnis des laufenden Prozesses, nicht im Verzeichnis der ausführbaren Datei.

Sie können den Dateinamen sowie den Ort, an dem Sisk nach der Konfigurationsdatei suchen soll, ändern mit:

```csharp
using Sisk.Core.Http;
using Sisk.Core.Http.Hosting;

using var app = HttpServer.CreateBuilder()
    .UsePortableConfiguration(config =>
    {
        config.WithConfigFile("config.toml",
            createIfDontExists: true,
            lookupDirectories:
                ConfigurationFileLookupDirectory.CurrentDirectory |
                ConfigurationFileLookupDirectory.AppDirectory);
    })
    .Build();
```

Der obige Code sucht die Datei `config.toml` im aktuellen Verzeichnis des laufenden Prozesses. Wird sie nicht gefunden, wird anschließend im Verzeichnis der ausführbaren Datei gesucht. Existiert die Datei nicht, wird der Parameter `createIfDontExists` berücksichtigt, die Datei (ohne Inhalt) im zuletzt getesteten Pfad (basierend auf `lookupDirectories`) erstellt, und es wird ein Fehler in der Konsole ausgegeben, der die Initialisierung der Anwendung verhindert.

> [!TIP]
> 
> Sie können sich den Quellcode des INI‑Konfigurationslesers und des JSON‑Konfigurationslesers ansehen, um zu verstehen, wie ein `IConfigurationProvider` implementiert ist.

## Lesen von Konfigurationen aus einer JSON‑Datei

Standardmäßig stellt Sisk einen Konfigurationsanbieter bereit, der Konfigurationen aus einer JSON‑Datei liest. Diese Datei folgt einer festen Struktur und besteht aus den folgenden Parametern:

```json
{
    "Server": {
        "DefaultEncoding": "UTF-8",
        "ThrowExceptions": true,
        "IncludeRequestIdHeader": true
    },
    "ListeningHost": {
        "Label": "My sisk application",
        "Ports": [
            "http://localhost:80/",
            "https://localhost:443/",  // Konfigurationsdateien unterstützen ebenfalls Kommentare
        ],
        "CrossOriginResourceSharingPolicy": {
            "AllowOrigin": "*",
            "AllowOrigins": [ "*" ],   // new on 0.14
            "AllowMethods": [ "*" ],
            "AllowHeaders": [ "*" ],
            "MaxAge": 3600
        },
        "Parameters": {
            "MySqlConnection": "server=localhost;user=root;"
        }
    }
}
```

Die aus einer Konfigurationsdatei erzeugten Parameter können im Server‑Konstruktor abgerufen werden:

```csharp
using var app = HttpServer.CreateBuilder()
    .UsePortableConfiguration(config =>
    {
        config.WithParameters(paramCollection =>
        {
            string databaseConnection = paramCollection.GetValueOrThrow("MySqlConnection");
        });
    })
    .Build();
```

Jeder Konfigurationsleser bietet eine Möglichkeit, die Server‑Initialisierungsparameter zu lesen. Einige Eigenschaften sollen in der Prozessumgebung angegeben werden, anstatt in der Konfigurationsdatei definiert zu sein, z. B. sensible API‑Daten, API‑Schlüssel usw.

## Struktur der Konfigurationsdatei

Die JSON‑Konfigurationsdatei besteht aus den folgenden Eigenschaften:

<table>
    <thead>
        <tr>
            <th>Eigenschaft</th>
            <th>Erforderlich</th>
            <th>Beschreibung</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Server</td>
            <td>Required</td>
            <td>Stellt den Server selbst mit seinen Einstellungen dar.</td>
        </tr>
        <tr>
            <td>Server.AccessLogsStream</td>
            <td>Optional</td>
            <td>Standardmäßig <code>console</code>. Gibt den Ausgabestream für das Zugriffsprotokoll an. Kann ein Dateiname, <code>null</code> oder <code>console</code> sein.</td>
        </tr>
        <tr>
            <td>Server.ErrorsLogsStream</td>
            <td>Optional</td>
            <td>Standardmäßig <code>null</code>. Gibt den Ausgabestream für das Fehlerprotokoll an. Kann ein Dateiname, <code>null</code> oder <code>console</code> sein.</td>
        </tr>
        <tr>
            <td>Server.MaximumContentLength</td>
            <td>Optional</td>
            <tr>
            <td>Server.MaximumContentLength</td>
            <td>Optional</td>
            <td>Gibt die maximale Inhaltslänge in Bytes an. Null bedeutet unbegrenzt. Wenn das <code>Server</code>-Objekt vorhanden ist und diese Eigenschaft weggelassen wird, ist der Wert <code>0</code> (unbegrenzt), was den Standardwert von 100 MB von <a href="/api/Sisk.Core.Http.HttpServerConfiguration.MaximumContentLength">HttpServerConfiguration.MaximumContentLength</a> überschreibt.</td>
        </tr>
        <tr>
            <td>Server.IncludeRequestIdHeader</td>
            <td>Optional</td>
            <td>Standardmäßig <code>false</code>. Gibt an, ob der HTTP‑Server den Header <code>X-Request-Id</code> senden soll.</td>
        </tr>
        <tr>
            <td>Server.ThrowExceptions</td>
            <td>Optional</td>
            <td>Standardmäßig <code>true</code>. Gibt an, ob nicht behandelte Ausnahmen geworfen werden sollen. In der Produktion auf <code>false</code> setzen und beim Debuggen auf <code>true</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost</td>
            <td>Required</td>
            <td>Stellt den Host dar, an dem der Server lauscht.</td>
        </tr>
        <tr>
            <td>ListeningHost.Label</td>
            <td>Optional</td>
            <td>Stellt die Anwendungsbezeichnung dar.</td>
        </tr>
        <tr>
            <td>ListeningHost.Ports</td>
            <td>Required</td>
            <td>Stellt ein Array von Zeichenketten dar, das der Syntax von <a href="/api/Sisk.Core.Http.ListeningPort">ListeningPort</a> entspricht.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy</td>
            <td>Optional</td>
            <td>Richtet die CORS‑Header für die Anwendung ein.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowCredentials</td>
            <td>Optional</td>
            <td>Standardmäßig <code>false</code>. Gibt den Header <code>Allow-Credentials</code> an.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.ExposeHeaders</td>
            <td>Optional</td>
            <td>Standardmäßig <code>null</code>. Diese Eigenschaft erwartet ein Array von Zeichenketten. Gibt den Header <code>Expose-Headers</code> an.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowOrigin</td>
            <td>Optional</td>
            <td>Standardmäßig <code>null</code>. Diese Eigenschaft erwartet eine Zeichenkette. Gibt den Header <code>Allow-Origin</code> an.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowOrigins</td>
            <td>Optional</td>
            <td>Standardmäßig <code>null</code>. Diese Eigenschaft erwartet ein Array von Zeichenketten. Gibt mehrere <code>Allow-Origin</code>-Header an. Siehe <a href="/api/Sisk.Core.Entity.CrossOriginResourceSharingHeaders.AllowOrigins">AllowOrigins</a> für weitere Informationen.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowMethods</td>
            <td>Optional</td>
            <td>Standardmäßig <code>null</code>. Diese Eigenschaft erwartet ein Array von Zeichenketten. Gibt den Header <code>Allow-Methods</code> an.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowHeaders</td>
            <td>Optional</td>
            <td>Standardmäßig <code>null</code>. Diese Eigenschaft erwartet ein Array von Zeichenketten. Gibt den Header <code>Allow-Headers</code> an.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.MaxAge</td>
            <td>Optional</td>
            <td>Standardmäßig <code>null</code>. Diese Eigenschaft erwartet einen Integer. Gibt den Header <code>Max-Age</code> in Sekunden an.</td>
        </tr>
        <tr>
            <td>ListeningHost.Parameters</td>
            <td>Optional</td>
            <td>Gibt die Eigenschaften an, die der Setup‑Methode der Anwendung übergeben werden.</td>
        </tr>
    </tbody>
</table>
