Udostępnij za pośrednictwem


ASP.NET Core Blazor plików statycznych

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz .NET i .NET Core Support Policy (Zasady obsługi platformy .NET Core). Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

Ważne

Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

W tym artykule opisano Blazor konfigurację aplikacji do obsługi plików statycznych.

Oprogramowanie pośredniczące statycznych zasobów

Ta sekcja dotyczy aplikacji po stronie Blazor serwera.

Obsługa zasobów statycznych jest zarządzana przez jedną z dwóch oprogramowania pośredniczącego opisanego w poniższej tabeli.

Oprogramowanie pośredniczące interfejs API Wersja platformy .NET opis
Mapowanie zasobów statycznych MapStaticAssets .NET 9 lub nowszy Optymalizuje dostarczanie zasobów statycznych klientom.
Pliki statyczne UseStaticFiles Wszystkie wersje platformy .NET Obsługuje zasoby statyczne dla klientów bez optymalizacji MapStaticAssets , ale przydatne w przypadku niektórych zadań, które MapStaticAssets nie są w stanie zarządzać.

Skonfiguruj oprogramowanie pośredniczące mapowania zasobów statycznych przez wywołanie MapStaticAssets w potoku przetwarzania żądań aplikacji, który wykonuje następujące czynności:

MapStaticAssets umożliwia łączenie procesów kompilacji i publikowania w celu zbierania informacji o zasobach statycznych w aplikacji. Te informacje są używane przez bibliotekę środowiska uruchomieniowego do wydajnego udostępniania zasobów statycznych przeglądarkom.

MapStaticAssets może zastąpić UseStaticFiles w większości sytuacji. Jest MapStaticAssets jednak zoptymalizowany pod kątem obsługi zasobów ze znanych lokalizacji w aplikacji w czasie kompilacji i publikowania. Jeśli aplikacja obsługuje zasoby z innych lokalizacji, takich jak dyski lub zasoby osadzone, UseStaticFiles powinny być używane.

MapStaticAssets zapewnia następujące korzyści, które nie są dostępne podczas wywoływania metody UseStaticFiles:

  • Kompresja czasu kompilacji dla wszystkich zasobów w aplikacji, w tym JavaScript (JS) i arkuszy stylów, ale z wyłączeniem zasobów obrazów i czcionek, które są już skompresowane. Kompresja Gzip (Content-Encoding: gz) jest używana podczas opracowywania. Kompresja Gzip z funkcją Brotli (Content-Encoding: br) jest używana podczas publikowania.
  • Odcisk palca dla wszystkich zasobów w czasie kompilacji z ciągiem zakodowanym w formacie Base64 skrótu SHA-256 zawartości każdego pliku. Zapobiega to ponownemu użyciu starej wersji pliku, nawet jeśli stary plik jest buforowany. Zasoby z odciskami palców są buforowane przy użyciu immutable dyrektywy , co powoduje, że przeglądarka nigdy nie zażąda zasobu ponownie, dopóki nie ulegnie zmianie. W przypadku przeglądarek, które nie obsługują immutable dyrektywy, max-age dodawana jest dyrektywa .
    • Nawet jeśli zasób nie jest odciskiem palca, zawartość jest ETags generowana dla każdego statycznego zasobu przy użyciu skrótu odcisku palca pliku jako ETag wartości. Dzięki temu przeglądarka pobiera plik tylko wtedy, gdy jego zawartość ulegnie zmianie (lub plik jest pobierany po raz pierwszy).
    • Blazor Wewnętrznie mapuje zasoby fizyczne na odciski palców, co umożliwia aplikacji:
      • Znajdź automatycznie generowane Blazor zasoby, takie jak Razor arkusz CSS o zakresie składników dla Blazorfunkcji izolacji CSS i JS zasoby opisane przez JS mapy importu.
      • Generowanie tagów linków w <head> zawartości strony w celu wstępnego ładowania zasobów.
  • Podczas testowania programistycznego Przeładowywanie na gorąco programu Visual Studio:
    • Informacje o integralności są usuwane z zasobów, aby uniknąć problemów podczas zmiany pliku podczas działania aplikacji.
    • Zasoby statyczne nie są buforowane, aby zapewnić, że przeglądarka zawsze pobiera bieżącą zawartość.

Gdy tryby interaktywnego zestawu WebAssembly lub interakcyjnego automatycznego renderowania są włączone:

  • Blazor tworzy punkt końcowy umożliwiający uwidocznienie kolekcji zasobów jako modułu JS .
  • Adres URL jest emitowany do treści żądania jako stan składnika utrwalonego, gdy składnik WebAssembly jest renderowany na stronie.
  • Podczas rozruchu Blazor zestawu WebAssembly pobiera adres URL, importuje moduł i wywołuje funkcję w celu pobrania kolekcji zasobów i odtworzenia jej w pamięci. Adres URL jest specyficzny dla zawartości i buforowany na zawsze, więc ten koszt narzucony jest opłacany tylko raz dla użytkownika, dopóki aplikacja nie zostanie zaktualizowana.
  • Kolekcja zasobów jest również widoczna pod adresem URL czytelnym dla człowieka (_framework/resource-collection.js), dlatego JS ma dostęp do kolekcji zasobów na potrzeby rozszerzonej nawigacji lub implementowania funkcji innych platform i składników innych firm.

Oprogramowanie pośredniczące mapowania zasobów statycznych nie udostępnia funkcji minimalnej ani innych przekształceń plików. Minimalnafikacja jest zwykle obsługiwana przez niestandardowy kod lub narzędzia innych firm.

Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) jest przydatne w następujących sytuacjach, które MapStaticAssets nie mogą obsłużyć:

Korzystanie z zasobów za pomocą oprogramowania pośredniczącego mapowania plików statycznych

Ta sekcja dotyczy aplikacji po stronie Blazor serwera.

Zasoby są używane za pośrednictwem ComponentBase.Assets właściwości , która rozpoznaje adres URL odcisku palca dla danego elementu zawartości. W poniższym przykładzie bootstrap, Blazor arkusz stylów aplikacji szablonu projektu (app.css) i arkusz stylów izolacji CSS są połączone w składniku głównym, zazwyczaj App składnik (Components/App.razor):

<link rel="stylesheet" href="@Assets["bootstrap/bootstrap.min.css"]" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["BlazorWeb-CSharp.styles.css"]" />

Importowanie map

Ta sekcja dotyczy aplikacji po stronie Blazor serwera.

Składnik ImportMap reprezentuje element mapy importu (<script type="importmap"></script>), który definiuje mapę importu dla skryptów modułów. Składnik ImportMap jest umieszczany w <head> zawartości składnika głównego, zazwyczaj App składnika (Components/App.razor).

<ImportMap />

Jeśli niestandardowy ImportMapDefinition element nie jest przypisany do ImportMap składnika, mapa importu jest generowana na podstawie zasobów aplikacji.

W poniższych przykładach pokazano niestandardowe definicje mapy importu i utworzone przez nich mapy importu.

Podstawowa mapa importu:

new ImportMapDefinition(
    new Dictionary<string, string>
    {
        { "jquery", "https://cdn.example.com/jquery.js" },
    },
    null,
    null);

Powyższy kod powoduje wykonanie następującej mapy importu:

{
  "imports": {
    "jquery": "https://cdn.example.com/jquery.js"
  }
}

Mapa importu o określonym zakresie:

new ImportMapDefinition(
    null,
    new Dictionary<string, IReadOnlyDictionary<string, string>>
    {
        ["/scoped/"] = new Dictionary<string, string>
        {
            { "jquery", "https://cdn.example.com/jquery.js" },
        }
    },
    null);

Powyższy kod powoduje wykonanie następującej mapy importu:

{
  "scopes": {
    "/scoped/": {
      "jquery": "https://cdn.example.com/jquery.js"
    }
  }
}

Importuj mapę z integralnością:

new ImportMapDefinition(
    new Dictionary<string, string>
    {
        { "jquery", "https://cdn.example.com/jquery.js" },
    },
    null,
    new Dictionary<string, string>
    {
        { "https://cdn.example.com/jquery.js", "sha384-abc123" },
    });

Powyższy kod powoduje wykonanie następującej mapy importu:

{
  "imports": {
    "jquery": "https://cdn.example.com/jquery.js"
  },
  "integrity": {
    "https://cdn.example.com/jquery.js": "sha384-abc123"
  }
}

Połącz definicje mapy importu (ImportMapDefinition) z ImportMapDefinition.Combine.

Zaimportuj mapę utworzoną na podstawie elementu ResourceAssetCollection , która mapuje zasoby statyczne na odpowiadające im unikatowe adresy URL:

ImportMapDefinition.FromResourceCollection(
    new ResourceAssetCollection(
    [
        new ResourceAsset(
            "jquery.fingerprint.js",
            [
                new ResourceAssetProperty("integrity", "sha384-abc123"),
                new ResourceAssetProperty("label", "jquery.js"),
            ])
    ]));

Powyższy kod powoduje wykonanie następującej mapy importu:

{
  "imports": {
    "./jquery.js": "./jquery.fingerprint.js"
  },
  "integrity": {
    "jquery.fingerprint.js": "sha384-abc123"
  }
}

Skonfiguruj oprogramowanie pośredniczące pliku statycznego w celu udostępniania statycznych zasobów klientom przez wywołanie UseStaticFiles w potoku przetwarzania żądań aplikacji. Aby uzyskać więcej informacji, zobacz Pliki statyczne platformy ASP.NET Core.

W wersjach wcześniejszych niż .NET 8 pliki statyczne platformy, Blazor takie jak Blazor skrypt, są obsługiwane za pośrednictwem oprogramowania pośredniczącego plików statycznych. W programie .NET 8 lub nowszym Blazor pliki statyczne platformy są mapowane przy użyciu routingu punktu końcowego, a oprogramowanie pośredniczące plików statycznych nie jest już używane.

Ta sekcja dotyczy wszystkich wersji i Blazor aplikacji platformy .NET.

W poniższych tabelach podsumowano formaty plików <link> href statycznych według wersji platformy .NET.

Aby uzyskać informacje o lokalizacji <head> zawartości, w której znajdują się linki do plików statycznych, zobacz ASP.NET Core project structure (Struktura projektu ASP.NET CoreBlazor). Statyczne linki zasobów można również dostarczać przy użyciu <HeadContent> składników w poszczególnych Razor składnikach.

Aby uzyskać informacje o lokalizacji <head> zawartości, w której znajdują się linki do plików statycznych, zobacz ASP.NET Core project structure (Struktura projektu ASP.NET CoreBlazor).

.NET 9 lub nowszy

Typ aplikacji href wartość Przykłady
Blazor Aplikacja internetowa @Assets["{PATH}"] <link rel="stylesheet" href="@Assets["app.css"]" />
<link href="@Assets["_content/ComponentLib/styles.css"]" rel="stylesheet" />
Blazor Server† @Assets["{PATH}"] <link href="@Assets["css/site.css"]" rel="stylesheet" />
<link href="@Assets["_content/ComponentLib/styles.css"]" rel="stylesheet" />
Autonomiczna Blazor WebAssembly {PATH} <link rel="stylesheet" href="css/app.css" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />

.NET 8.x

Typ aplikacji href wartość Przykłady
Blazor Aplikacja internetowa {PATH} <link rel="stylesheet" href="app.css" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />
Blazor Server† {PATH} <link href="css/site.css" rel="stylesheet" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />
Autonomiczna Blazor WebAssembly {PATH} <link rel="stylesheet" href="css/app.css" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />

.NET 7.x lub starszy

Typ aplikacji href wartość Przykłady
Blazor Server† {PATH} <link href="css/site.css" rel="stylesheet" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />
Hostowana Blazor WebAssembly( ) {PATH} <link href="css/app.css" rel="stylesheet" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />
Blazor WebAssembly {PATH} <link href="css/app.css" rel="stylesheet" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />

Blazor Server† jest obsługiwana na platformie .NET 8 lub nowszym, ale nie jest już szablonem projektu po programie .NET 7.
{Zalecamy zaktualizowanie hostowanych Blazor WebAssembly aplikacji do Blazor usługi Web Apps podczas wdrażania platformy .NET 8 lub nowszej.

Tryb projektu statycznego zasobu internetowego

Ta sekcja dotyczy .Client projektu Blazor aplikacji internetowej.

Wymagane <StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode> ustawienie w .Client projekcie Blazor aplikacji internetowej przywraca Blazor WebAssembly statyczne zachowania zasobów z powrotem do wartości domyślnych, tak aby projekt zachowywał się jako część hostowanego projektu. Zestaw Blazor WebAssembly SDK (Microsoft.NET.Sdk.BlazorWebAssembly) konfiguruje statyczne zasoby internetowe w określony sposób, aby działały w trybie "autonomicznym" przy użyciu serwera po prostu zużywając dane wyjściowe z biblioteki. Nie jest to odpowiednie dla Blazor aplikacji internetowej, gdzie część webAssembly aplikacji jest logiczną częścią hosta i musi zachowywać się bardziej jak biblioteka. Na przykład projekt nie uwidacznia pakietu stylów (na przykład BlazorSample.Client.styles.css) i zamiast tego udostępnia hostowi tylko pakiet projektu, dzięki czemu host może uwzględnić go we własnym pakiecie stylów.

Zmiana wartości (Default) <StaticWebAssetProjectMode> lub usunięcia właściwości z .Client projektu nie jest obsługiwana.

Pliki statyczne w środowiskach innych niżDevelopment

Ta sekcja dotyczy plików statycznych po stronie serwera.

W przypadku lokalnego uruchamiania aplikacji statyczne zasoby internetowe są domyślnie włączone tylko w Development środowisku. Aby włączyć pliki statyczne dla środowisk innych niż Development podczas lokalnego programowania i testowania (na przykład Staging), wywołaj WebApplicationBuilder UseStaticWebAssets element w Program pliku .

Ostrzeżenie

Wywołaj UseStaticWebAssets dokładne środowisko, aby zapobiec aktywowaniu funkcji w środowisku produkcyjnym, ponieważ obsługuje pliki z oddzielnych lokalizacji na dysku innym niż projekt, jeśli jest wywoływany w środowisku produkcyjnym. Przykład w tej sekcji sprawdza Staging środowisko przez wywołanie metody IsStaging.

if (builder.Environment.IsStaging())
{
    builder.WebHost.UseStaticWebAssets();
}

Prefiks dla Blazor WebAssembly zasobów

Ta sekcja dotyczy Blazor usługi Web Apps.

Użyj opcji punktu końcowego WebAssemblyComponentsEndpointOptions.PathPrefix , aby ustawić ciąg ścieżki wskazujący prefiks dla Blazor WebAssembly zasobów. Ścieżka musi odpowiadać projektowi Blazor WebAssembly aplikacji, do których się odwołujesz.

endpoints.MapRazorComponents<App>()
    .AddInteractiveWebAssemblyRenderMode(options => 
        options.PathPrefix = "{PATH PREFIX}");

W poprzednim przykładzie {PATH PREFIX} symbol zastępczy jest prefiksem ścieżki i musi zaczynać się od ukośnika (/).

W poniższym przykładzie prefiks ścieżki jest ustawiony na /path-prefix:

endpoints.MapRazorComponents<App>()
    .AddInteractiveWebAssemblyRenderMode(options => 
        options.PathPrefix = "/path-prefix");

Statyczna ścieżka podstawowa zasobu internetowego

Ta sekcja dotyczy aplikacji autonomicznych Blazor WebAssembly .

Domyślnie publikowanie aplikacji umieszcza statyczne zasoby aplikacji, w tym Blazor pliki struktury (_framework zasoby folderów), w ścieżce głównej (/) w opublikowanych danych wyjściowych. Właściwość określona <StaticWebAssetBasePath> w pliku projektu (.csproj) ustawia ścieżkę podstawową na ścieżkę inną niż główna:

<PropertyGroup>
  <StaticWebAssetBasePath>{PATH}</StaticWebAssetBasePath>
</PropertyGroup>

W poprzednim przykładzie {PATH} symbol zastępczy to ścieżka.

Bez ustawiania <StaticWebAssetBasePath> właściwości aplikacja autonomiczna jest publikowana pod adresem /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/.

W poprzednim przykładzie {TFM} symbol zastępczy to Target Framework Moniker (TFM) (na przykład net6.0).

<StaticWebAssetBasePath> Jeśli właściwość w aplikacji autonomicznej Blazor WebAssembly ustawia opublikowaną statyczną ścieżkę zasobu na app1wartość , ścieżka główna do aplikacji w opublikowanych danych wyjściowych to /app1.

W pliku projektu aplikacji autonomicznej Blazor WebAssembly (.csproj):

<PropertyGroup>
  <StaticWebAssetBasePath>app1</StaticWebAssetBasePath>
</PropertyGroup>

W opublikowanych danych wyjściowych ścieżka do aplikacji autonomicznej Blazor WebAssembly to /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/.

W poprzednim przykładzie {TFM} symbol zastępczy to Target Framework Moniker (TFM) (na przykład net6.0).

Ta sekcja dotyczy Blazor WebAssembly autonomicznych aplikacji i hostowanych Blazor WebAssembly rozwiązań.

Domyślnie publikowanie aplikacji umieszcza statyczne zasoby aplikacji, w tym Blazor pliki struktury (_framework zasoby folderów), w ścieżce głównej (/) w opublikowanych danych wyjściowych. Właściwość określona <StaticWebAssetBasePath> w pliku projektu (.csproj) ustawia ścieżkę podstawową na ścieżkę inną niż główna:

<PropertyGroup>
  <StaticWebAssetBasePath>{PATH}</StaticWebAssetBasePath>
</PropertyGroup>

W poprzednim przykładzie {PATH} symbol zastępczy to ścieżka.

Bez ustawiania <StaticWebAssetBasePath> właściwości aplikacja kliencka hostowanego rozwiązania lub aplikacji autonomicznej jest publikowana w następujących ścieżkach:

  • W projekcie Server rozwiązania hostowanego Blazor WebAssembly : /BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/
  • W aplikacji autonomicznej Blazor WebAssembly : /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/

<StaticWebAssetBasePath> Jeśli właściwość w Client projekcie hostowanej Blazor WebAssembly aplikacji lub w autonomicznej Blazor WebAssembly aplikacji ustawia opublikowaną ścieżkę statycznego zasobu na app1, ścieżka główna do aplikacji w opublikowanych danych wyjściowych to /app1.

Client W pliku projektu aplikacji (.csproj) lub pliku projektu aplikacji autonomicznej Blazor WebAssembly (.csproj):

<PropertyGroup>
  <StaticWebAssetBasePath>app1</StaticWebAssetBasePath>
</PropertyGroup>

W opublikowanych danych wyjściowych:

  • Ścieżka do aplikacji klienckiej w Server projekcie hostowanego Blazor WebAssembly rozwiązania: /BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/app1/
  • Ścieżka do aplikacji autonomicznej Blazor WebAssembly : /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/

Właściwość jest najczęściej używana do kontrolowania <StaticWebAssetBasePath> ścieżek do opublikowanych zasobów statycznych wielu Blazor WebAssembly aplikacji w jednym hostowanym wdrożeniu. Aby uzyskać więcej informacji, zobacz Wiele hostowanych aplikacji ASP.NET CoreBlazor WebAssembly. Właściwość jest również skuteczna w aplikacjach autonomicznych Blazor WebAssembly .

W poprzednich przykładach {TFM} symbol zastępczy to Target Framework Moniker (TFM) (na przykład net6.0).

Mapowania plików i opcje plików statycznych

Ta sekcja dotyczy plików statycznych po stronie serwera.

Aby utworzyć dodatkowe mapowania plików za pomocą elementu FileExtensionContentTypeProvider lub skonfigurować inne StaticFileOptions, użyj jednej z poniższych metod. W poniższych przykładach {EXTENSION} symbol zastępczy jest rozszerzeniem pliku, a {CONTENT TYPE} symbol zastępczy jest typem zawartości. Przestrzeń nazw dla następującego interfejsu API to Microsoft.AspNetCore.StaticFiles.

  • Skonfiguruj opcje za pomocą wstrzykiwania zależności (DI) w Program pliku przy użyciu polecenia StaticFileOptions:

    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    builder.Services.Configure<StaticFileOptions>(options =>
    {
        options.ContentTypeProvider = provider;
    });
    
    app.UseStaticFiles();
    
  • Przekaż plik StaticFileOptions bezpośrednio do UseStaticFiles pliku Program :

    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
    

Aby utworzyć dodatkowe mapowania plików za pomocą elementu FileExtensionContentTypeProvider lub skonfigurować inne StaticFileOptions, użyj jednej z poniższych metod. W poniższych przykładach {EXTENSION} symbol zastępczy jest rozszerzeniem pliku, a {CONTENT TYPE} symbol zastępczy jest typem zawartości.

  • Skonfiguruj opcje za pomocą wstrzykiwania zależności (DI) w Program pliku przy użyciu polecenia StaticFileOptions:

    using Microsoft.AspNetCore.StaticFiles;
    
    ...
    
    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    builder.Services.Configure<StaticFileOptions>(options =>
    {
        options.ContentTypeProvider = provider;
    });
    

    To podejście umożliwia skonfigurowanie tego samego dostawcy plików używanego do obsługi skryptu Blazor . Upewnij się, że konfiguracja niestandardowa nie zakłóca obsługi skryptu Blazor . Na przykład nie usuwaj mapowania plików JavaScript, konfigurując dostawcę za pomocą provider.Mappings.Remove(".js")polecenia .

  • W pliku użyj dwóch wywołań UseStaticFiles Program :

    • Skonfiguruj niestandardowego dostawcę plików w pierwszym wywołaniu za pomocą polecenia StaticFileOptions.
    • Drugie oprogramowanie pośredniczące obsługuje Blazor skrypt, który używa domyślnej konfiguracji plików statycznych udostępnianych przez platformę Blazor .
    using Microsoft.AspNetCore.StaticFiles;
    
    ...
    
    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
    app.UseStaticFiles();
    
  • Możesz uniknąć zakłócania obsługi _framework/blazor.server.js przy użyciu polecenia w MapWhen celu wykonania niestandardowego oprogramowania pośredniczącego plików statycznych:

    app.MapWhen(ctx => !ctx.Request.Path
        .StartsWithSegments("/_framework/blazor.server.js"),
            subApp => subApp.UseStaticFiles(new StaticFileOptions() { ... }));
    

Dodatkowe zasoby