Udostępnij za pośrednictwem


Integrowanie składników ASP.NET Core Razor z architekturą MVC lub Razor stronami w rozwiązaniach hostowanych Blazor WebAssembly

Uwaga

Hostowane Blazor WebAssembly rozwiązania pozostają obsługiwane, ale szablon projektu został usunięty i nie jest już obsługiwany na platformie .NET 8 lub nowszym. Ten artykuł pojawia się w spisie treści do platformy .NET 7 do celów referencyjnych, ale należy pamiętać, że platforma .NET 7 jest wersją standardową terminu pomocy technicznej, która nie jest już obsługiwana.

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core.

W tym artykule opisano Razor scenariusze integracji składników dla hostowanych Blazor WebAssembly aplikacji, w tym wstępne tworzenie składników Razor na serwerze.

Ważne

Zmiany struktury w wersjach ASP.NET Core doprowadziły do różnych zestawów instrukcji w tym artykule. Przed użyciem wskazówek w tym artykule upewnij się, że selektor wersji dokumentu w górnej części tego artykułu jest zgodny z wersją ASP.NET Core, która ma być używana dla aplikacji.

Prerendering może poprawić optymalizację aparatu wyszukiwania (SEO) przez renderowanie zawartości początkowej odpowiedzi HTTP, za pomocą których wyszukiwarki mogą obliczyć rangę strony.

Konfiguracja rozwiązania

Konfiguracja prerenderingu

Aby skonfigurować wstępne ustawianie aplikacji hostowanej Blazor WebAssembly :

  1. Hostowanie Blazor WebAssembly aplikacji w aplikacji ASP.NET Core. Aplikację autonomiczną Blazor WebAssembly można dodać do rozwiązania ASP.NET Core lub użyć hostowanej Blazor WebAssembly aplikacji utworzonej Blazor WebAssembly na podstawie szablonu projektu z opcją hostowaną:

    • Visual Studio: w oknie dialogowym Dodatkowe informacje zaznacz pole wyboru ASP.NET Core Hosted podczas tworzenia Blazor WebAssembly aplikacji. W przykładach tego artykułu rozwiązanie nosi nazwę BlazorHosted.
    • Powłoka poleceń interfejsu -ho|--hosted wiersza polecenia programu Visual Studio Code/.NET: dotnet new blazorwasm -ho (użyj opcji). -o|--output {LOCATION} Użyj opcji , aby utworzyć folder dla rozwiązania i ustawić przestrzenie nazw projektu rozwiązania. W przykładach tego artykułu rozwiązanie nosi nazwę BlazorHosted (dotnet new blazorwasm -ho -o BlazorHosted).

    W przykładach w tym artykule nazwa hostowanego rozwiązania (nazwa zestawu) to BlazorHosted. Przestrzeń nazw projektu klienta to BlazorHosted.Client, a przestrzeń nazw projektu serwera to BlazorHosted.Server.

  2. wwwroot/index.html Usuń plik z Blazor WebAssemblyClient projektu.

  3. W projekcie Client usuń następujące wiersze w pliku Program.cs:

    - builder.RootComponents.Add<App>("#app");
    - builder.RootComponents.Add<HeadOutlet>("head::after");
    
  4. Dodaj _Host.cshtml plik do Server folderu projektu Pages . Pliki można uzyskać z projektu utworzonego Blazor Server na podstawie szablonu przy użyciu programu Visual Studio lub interfejsu wiersza polecenia platformy .NET za dotnet new blazorserver -o BlazorServer pomocą polecenia w powłoce poleceń ( -o BlazorServer opcja tworzy folder dla projektu). Po umieszczeniu plików w Server folderze projektu Pages wprowadź następujące zmiany w plikach.

    Wprowadź następujące zmiany w _Host.cshtml pliku:

    • Pages Zaktualizuj przestrzeń nazw w górnej części pliku, aby odpowiadała przestrzeni nazw Server stron aplikacji. Symbol {APP NAMESPACE} zastępczy w poniższym przykładzie reprezentuje przestrzeń nazw stron aplikacji dawcy, które dostarczyły _Host.cshtml pliku:

      Usuwanie:

      - @namespace {APP NAMESPACE}.Pages
      

      Dodaj:

      @namespace BlazorHosted.Server.Pages
      
    • Dodaj dyrektywę @using dla Client projektu w górnej części pliku:

      @using BlazorHosted.Client
      
    • Zaktualizuj łącza arkusza stylów, aby wskazywały arkusze stylów projektu WebAssembly. W poniższym przykładzie przestrzeń nazw projektu klienta to BlazorHosted.Client. Symbol {APP NAMESPACE} zastępczy reprezentuje przestrzeń nazw aplikacji dawcy, która dostarczyła _Host.cshtml plik. Zaktualizuj pomocnik tagu składnika (<component> tag) dla HeadOutlet składnika, aby wstępnie przygotować składnik.

      Usuwanie:

      - <link href="css/site.css" rel="stylesheet" />
      - <link href="{APP NAMESPACE}.styles.css" rel="stylesheet" />
      - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
      

      Dodaj:

      <link href="css/app.css" rel="stylesheet" />
      <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
      <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
      

      Uwaga

      <link> Pozostaw element, który żąda arkusza stylów Bootstrap (css/bootstrap/bootstrap.min.css) na miejscu.

    • Zaktualizuj źródło skryptu, Blazor aby użyć skryptu po stronie Blazor WebAssembly klienta:

      Usuwanie:

      - <script src="_framework/blazor.server.js"></script>
      

      Dodaj:

      <script src="_framework/blazor.webassembly.js"></script>
      
    • render-mode Zaktualizuj pomocnik tagu składnika, aby wstępnie wstępnie udostępnić składnik główny App za pomocą polecenia WebAssemblyPrerendered:

      Usuwanie:

      - <component type="typeof(App)" render-mode="ServerPrerendered" />
      

      Dodaj:

      <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
      

      Ważne

      Prerendering nie jest obsługiwany w przypadku punktów końcowych uwierzytelniania (/authentication/ segment ścieżki). Aby uzyskać więcej informacji, zobacz Dodatkowe scenariusze zabezpieczeń zestawu ASP.NET Core Blazor WebAssembly.

  5. Program.cs W pliku Server projektu zmień rezerwowy punkt końcowy z index.html pliku na _Host.cshtml stronę:

    Usuwanie:

    - app.MapFallbackToFile("index.html");
    

    Dodaj:

    app.MapFallbackToPage("/_Host");
    
  6. Jeśli projekty Client i Server używają co najmniej jednej typowej usługi podczas prerenderingu, należy uwzględnić rejestracje usługi w metodzie, którą można wywołać z obu projektów. Aby uzyskać więcej informacji, zobacz ASP.NET Core dependency injection (Wstrzykiwanie zależności ASP.NET CoreBlazor).

  7. Server Uruchom projekt. Blazor WebAssembly Hostowana aplikacja jest wstępnie obsługiwana Server przez projekt dla klientów.

Konfiguracja osadzania Razor składników na stronach lub widokach

Poniższe sekcje i przykłady osadzania Razor składników z ClientBlazor WebAssembly aplikacji na stronach lub widokach aplikacji serwera wymagają dodatkowej konfiguracji.

Projekt Server musi mieć następujące pliki i foldery.

Razor Stron:

  • Pages/Shared/_Layout.cshtml
  • Pages/Shared/_Layout.cshtml.css
  • Pages/_ViewImports.cshtml
  • Pages/_ViewStart.cshtml

MVC:

  • Views/Shared/_Layout.cshtml
  • Views/Shared/_Layout.cshtml.css
  • Views/_ViewImports.cshtml
  • Views/_ViewStart.cshtml

Powyższe pliki można uzyskać, generując aplikację z szablonów projektów platformy ASP.NET Core przy użyciu:

  • Nowe narzędzia do tworzenia projektów programu Visual Studio.
  • Otwieranie powłoki poleceń i wykonywanie dotnet new webapp -o {PROJECT NAME} (Razor Pages) lub dotnet new mvc -o {PROJECT NAME} (MVC). Opcja -o|--output z wartością symbolu zastępczego {PROJECT NAME} zawiera nazwę aplikacji i tworzy folder dla aplikacji.

Zaktualizuj przestrzenie nazw w zaimportowanych _ViewImports.cshtml plikach, aby były zgodne z tymi, które są używane przez Server projekt odbierający pliki.

Pages/_ViewImports.cshtml (Razor Strony):

@using BlazorHosted.Server
@namespace BlazorHosted.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Views/_ViewImports.cshtml (MVC):

@using BlazorHosted.Server
@using BlazorHosted.Server.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Zaktualizuj zaimportowany plik układu, który jest Pages/Shared/_Layout.cshtml przeznaczony dla Razor stron lub Views/Shared/_Layout.cshtml MVC.

Najpierw usuń tytuł i arkusz stylów z projektu darczyńców, który znajduje się RPDonor.styles.css w poniższym przykładzie. Symbol {PROJECT NAME} zastępczy reprezentuje nazwę aplikacji projektu darczyńcy.

- <title>@ViewData["Title"] - {PROJECT NAME}</title>
- <link rel="stylesheet" href="~/RPDonor.styles.css" asp-append-version="true" />

Uwzględnij Client style projektu w pliku układu. W poniższym przykładzie Client przestrzeń nazw projektu to BlazorHosted.Client. Element <title> można zaktualizować w tym samym czasie.

Umieść następujące wiersze w <head> zawartości pliku układu:

<title>@ViewData["Title"] - BlazorHosted</title>
<link href="css/app.css" rel="stylesheet" />
<link rel="stylesheet" href="BlazorHosted.Client.styles.css" asp-append-version="true" />
<component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />

Zaimportowany układ zawiera dwa Home (Index strona) i Privacy linki nawigacji. Aby połączyć Home się z hostowaną Blazor WebAssembly aplikacją, zmień hiperlinki:

- <a class="navbar-brand" asp-area="" asp-page="/Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

W pliku układu MVC:

- <a class="navbar-brand" asp-area="" asp-controller="Home" 
-     asp-action="Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-controller="Home" 
-     asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

<footer> Zaktualizuj nazwę aplikacji elementu. W poniższym przykładzie użyto nazwy BlazorHostedaplikacji :

- &copy; {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ &copy; {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>

W poprzednim przykładzie {DATE} symbol zastępczy reprezentuje datę praw autorskich w aplikacji wygenerowanej Razor na podstawie szablonu projektu Pages lub MVC.

Aby utworzyć Privacy link prowadzący do privacy strony (Razor Strony), dodaj privacy stronę do Server projektu.

Pages/Privacy.cshtml w projekcie Server :

@page
@model PrivacyModel
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

W przypadku widoku opartego na privacy mvC utwórz privacy widok w projekcie Server .

View/Home/Privacy.cshtml w projekcie Server :

@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

W kontrolerze Home aplikacji MVC zwróć widok.

Dodaj następujący kod do pliku Controllers/HomeController.cs:

public IActionResult Privacy()
{
    return View();
}

W przypadku importowania plików z aplikacji darczyńców pamiętaj, aby zaktualizować wszystkie przestrzenie nazw w plikach tak, BlazorHosted.Serveraby pasły Server do tego projektu (na przykład ).

Zaimportuj Server zasoby statyczne do projektu z folderu projektu darczyńców wwwroot :

  • wwwroot/css folder i zawartość
  • wwwroot/js folder i zawartość
  • wwwroot/lib folder i zawartość

Jeśli projekt darczyńcy zostanie utworzony na podstawie szablonu projektu ASP.NET Core i pliki nie zostaną zmodyfikowane, możesz skopiować cały wwwroot folder z projektu darczyńców do Server projektu i usunąć favicon plik ikony.

Ostrzeżenie

Unikaj umieszczania statycznego elementu zawartości w folderach Client i .Server wwwroot Jeśli ten sam plik znajduje się w obu folderach, zgłaszany jest wyjątek, ponieważ statyczne zasoby współużytkują tę samą ścieżkę katalogu głównego sieci Web. W związku z tym hostowanie elementu zawartości statycznej w jednym z wwwroot folderów, a nie obu tych folderów.

Po wdrożeniu poprzedniej konfiguracji osadź Razor składniki na stronach lub widokach Server projektu. Skorzystaj ze wskazówek w następujących sekcjach tego artykułu:

  • Renderowanie składników na stronie lub widoku za pomocą pomocnika tagów składników
  • Renderowanie składników na stronie lub widoku za pomocą selektora CSS

Renderowanie składników na stronie lub widoku za pomocą pomocnika tagów składników

Po skonfigurowaniu rozwiązania, w tym dodatkowej konfiguracji, pomocnik tagu składnika obsługuje dwa tryby renderowania składnika do renderowania składnika z Blazor WebAssembly aplikacji na stronie lub widoku:

W poniższym Razor przykładzie Counter strony składnik jest renderowany na stronie. Aby składnik był interaktywny, Blazor WebAssembly skrypt jest zawarty w sekcji renderowania strony. Aby uniknąć używania pełnej przestrzeni nazw składnika Counter z pomocnikiem tagów składników ({ASSEMBLY NAME}.Pages.Counter), dodaj dyrektywę @using dla przestrzeni nazw projektu Pages klienta. W poniższym przykładzie Client przestrzeń nazw projektu to BlazorHosted.Client.

W projekcieServer Pages/RazorPagesCounter1.cshtml:

@page
@using BlazorHosted.Client.Pages

<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Server Uruchom projekt. Przejdź do Razor strony pod adresem /razorpagescounter1. Składnik prerendered Counter jest osadzony na stronie.

RenderMode konfiguruje, czy składnik:

  • Jest wstępnie załadowany do strony.
  • Jest renderowany jako statyczny kod HTML na stronie lub jeśli zawiera informacje niezbędne do uruchomienia Blazor aplikacji z agenta użytkownika.

Aby uzyskać więcej informacji na temat pomocnika tagów składników, w tym przekazywania parametrów i RenderMode konfiguracji, zobacz Pomocnik tagów składników w ASP.NET Core.

W zależności od zasobów statycznych używanych przez składniki i sposobu organizowania stron układu w aplikacji może być wymagana dodatkowa praca. Zazwyczaj skrypty są dodawane do sekcji renderowania Scripts strony lub widoku, a arkusze stylów są dodawane do zawartości elementu układu <head> .

Ustawianie zawartości podrzędnej za pomocą fragmentu renderowania

Pomocnik tagów składników nie obsługuje odbierania delegata RenderFragment dla zawartości podrzędnej (na przykład param-ChildContent="..."). Zalecamy utworzenie Razor składnika (.razor), który odwołuje się do składnika, który ma być renderowany przy użyciu zawartości podrzędnej, którą chcesz przekazać, a następnie wywołania Razor składnika ze strony lub widoku.

Upewnij się, że składniki wstępne najwyższego poziomu nie są przycinane podczas publikowania

Jeśli Pomocnik tagów składników bezpośrednio odwołuje się do składnika z biblioteki, która podlega przycinaniu podczas publikowania, składnik może zostać przycięty podczas publikowania, ponieważ nie ma do niego odwołań z kodu aplikacji po stronie klienta. W związku z tym składnik nie jest wstępnie ustawiony, pozostawiając puste miejsce w danych wyjściowych. W takim przypadku poinstruuj program trimmer, aby zachował składnik biblioteki, dodając DynamicDependency atrybut do dowolnej klasy w aplikacji po stronie klienta. Aby zachować składnik o nazwie SomeLibraryComponentToBePreserved, dodaj następujący element do dowolnego składnika:

@using System.Diagnostics.CodeAnalysis
@attribute [DynamicDependency(DynamicallyAccessedMemberTypes.All, 
    typeof(SomeLibraryComponentToBePreserved))]

Powyższe podejście zwykle nie jest wymagane, ponieważ aplikacja zwykle prerenders jej składniki (które nie są przycinane), co z kolei odwołuje się do składników bibliotek (co powoduje, że nie są one również przycinane). Jawnie używaj DynamicDependency tylko do prerenderingu składnika biblioteki bezpośrednio, gdy biblioteka podlega przycinaniu.

Renderowanie składników na stronie lub widoku za pomocą selektora CSS

Po skonfigurowaniu rozwiązania, w tym dodatkowej konfiguracji, dodaj składniki główne do Client projektu hostowanego Blazor WebAssembly rozwiązania w Program.cs pliku. W poniższym przykładzie Counter składnik jest zadeklarowany jako składnik główny z selektorem CSS, który wybiera element z elementem id counter-componentzgodnym z elementem . W poniższym przykładzie Client przestrzeń nazw projektu to BlazorHosted.Client.

W Program.cs pliku Client projektu dodaj przestrzeń nazw składników projektu Razor na początku pliku:

using BlazorHosted.Client.Pages;

Po ustanowieniu elementu Counter w Program.cselemencie builder dodaj składnik jako składnik główny:

builder.RootComponents.Add<Counter>("#counter-component");

W poniższym Razor przykładzie Counter strony składnik jest renderowany na stronie. Aby składnik był interaktywny, Blazor WebAssembly skrypt jest zawarty w sekcji renderowania strony.

W projekcieServer Pages/RazorPagesCounter2.cshtml:

@page

<div id="counter-component">Loading...</div>

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Server Uruchom projekt. Przejdź do Razor strony pod adresem /razorpagescounter2. Składnik prerendered Counter jest osadzony na stronie.

W zależności od zasobów statycznych używanych przez składniki i sposobu organizowania stron układu w aplikacji może być wymagana dodatkowa praca. Zazwyczaj skrypty są dodawane do sekcji renderowania Scripts strony lub widoku, a arkusze stylów są dodawane do zawartości elementu układu <head> .

Uwaga

Powyższy przykład zgłasza błąd JSException , jeśli Blazor WebAssembly aplikacja jest wstępnie wstępnie wstępnie zintegrowana z aplikacją Razor Pages lub MVC jednocześnie z użyciem selektora CSS. Przejście do jednego ze Client składników projektu Razor lub przejście do strony lub widoku obiektu Server z osadzonym składnikiem zgłasza co najmniej jeden JSExceptionelement .

Jest to normalne zachowanie, ponieważ wstępne tworzenie i integrowanie Blazor WebAssembly aplikacji ze składnikami routingu Razor jest niezgodne z użyciem selektorów CSS.

Jeśli pracujesz z przykładami w poprzednich sekcjach i chcesz zobaczyć, jak selektor CSS działa w przykładowej aplikacji, oznacz specyfikację App składnika Client głównego pliku projektu Program.cs :

- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");

Przejdź do strony lub widoku z osadzonym Razor składnikiem, który używa selektora CSS (na przykład /razorpagescounter2 z poprzedniego przykładu). Strona lub widok są ładowane z osadzonym składnikiem, a osadzony składnik działa zgodnie z oczekiwaniami.

Utrwalanie stanu wstępnego

Bez utrwalania stanu wstępnego, stan używany podczas prerenderingu jest utracony i musi zostać utworzony ponownie, gdy aplikacja jest w pełni załadowana. Jeśli jakikolwiek stan jest skonfigurowany asynchronicznie, interfejs użytkownika może migać, ponieważ wstępnie wypełniony interfejs użytkownika jest zastępowany symbolami zastępczymi tymczasowymi, a następnie w pełni renderowany ponownie.

Aby utrwały stan dla wstępnie wstępnie użytych składników, należy użyć pomocnika tagu stanu składnika (źródło referencyjne). Dodaj tag <persist-component-state />Pomocnika tagu , wewnątrz tagu _Host zamykającego </body> strony w aplikacji, która prerenders składników.

Uwaga

Linki dokumentacji do źródła referencyjnego platformy .NET zwykle ładują domyślną gałąź repozytorium, która odzwierciedla bieżące programowanie dla następnej wersji platformy .NET. Aby wybrać tag dla określonej wersji, użyj listy rozwijanej Przełącz gałęzie lub tagi. Aby uzyskać więcej informacji, zobacz Jak wybrać tag wersji kodu źródłowego platformy ASP.NET Core (dotnet/AspNetCore.Docs #26205).

W Pages/_Host.cshtml aplikacjach Blazor , które są wstępnie obsługiwane przez zestaw WebAssembly (WebAssemblyPrerendered) w hostowanej Blazor WebAssembly aplikacji:

<body>
    ...

    <persist-component-state />
</body>

Zdecyduj, jaki stan ma być trwały przy użyciu PersistentComponentState usługi. PersistentComponentState.RegisterOnPersisting rejestruje wywołanie zwrotne, aby utrwało stan składnika przed wstrzymaniem aplikacji. Stan jest pobierany po wznowieniu działania aplikacji.

W poniższym przykładzie:

  • Symbol {TYPE} zastępczy reprezentuje typ danych do utrwalania (na przykład WeatherForecast[]).
  • Symbol {TOKEN} zastępczy jest ciągiem identyfikatora stanu (na przykład fetchdata).
@implements IDisposable
@inject PersistentComponentState ApplicationState

...

@code {
    private {TYPE} data;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = 
            ApplicationState.RegisterOnPersisting(PersistData);

        if (!ApplicationState.TryTakeFromJson<{TYPE}>(
            "{TOKEN}", out var restored))
        {
            data = await ...;
        }
        else
        {
            data = restored!;
        }
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson("{TOKEN}", data);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

Poniższy przykład to zaktualizowana wersja FetchData składnika w hostowanej Blazor WebAssembly aplikacji na podstawie szablonu Blazor projektu. Składnik WeatherForecastPreserveState utrzymuje stan prognozy pogody podczas prerenderingu, a następnie pobiera stan w celu zainicjowania składnika. Pomocnik stanu stanu składnika utrwala stan składnika po wywołaniach wszystkich składników.

Pages/WeatherForecastPreserveState.razor:

@page "/weather-forecast-preserve-state"
@using BlazorSample.Shared
@implements IDisposable
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState

<PageTitle>Weather Forecast</PageTitle>

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = 
            ApplicationState.RegisterOnPersisting(PersistForecasts);

        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            "fetchdata", out var restored))
        {
            forecasts = 
                await WeatherForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
        }
        else
        {
            forecasts = restored!;
        }
    }

    private Task PersistForecasts()
    {
        ApplicationState.PersistAsJson("fetchdata", forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

Inicjując składniki o tym samym stanie używanym podczas prerenderingu, wszystkie kosztowne kroki inicjowania są wykonywane tylko raz. Renderowany interfejs użytkownika jest również zgodny ze wstępnie zdefiniowanym interfejsem użytkownika, więc w przeglądarce nie występuje migotanie.

Stan utrwalonego wstępnego jest przenoszony do klienta, gdzie jest używany do przywrócenia stanu składnika. W przypadku wstępnego przetwarzania w aplikacji hostowanej Blazor WebAssembly dane są udostępniane w przeglądarce i nie mogą zawierać poufnych, prywatnych informacji.

Dodatkowe Blazor WebAssembly zasoby

Prerendering może poprawić optymalizację aparatu wyszukiwania (SEO) przez renderowanie zawartości początkowej odpowiedzi HTTP, za pomocą których wyszukiwarki mogą obliczyć rangę strony.

Konfiguracja rozwiązania

Konfiguracja prerenderingu

Aby skonfigurować wstępne ustawianie aplikacji hostowanej Blazor WebAssembly :

  1. Hostowanie Blazor WebAssembly aplikacji w aplikacji ASP.NET Core. Aplikację autonomiczną Blazor WebAssembly można dodać do rozwiązania ASP.NET Core lub użyć hostowanej Blazor WebAssembly aplikacji utworzonej Blazor WebAssembly na podstawie szablonu projektu z opcją hostowaną:

    • Visual Studio: w oknie dialogowym Dodatkowe informacje zaznacz pole wyboru ASP.NET Core Hosted podczas tworzenia Blazor WebAssembly aplikacji. W przykładach tego artykułu rozwiązanie nosi nazwę BlazorHosted.
    • Powłoka poleceń interfejsu -ho|--hosted wiersza polecenia programu Visual Studio Code/.NET: dotnet new blazorwasm -ho (użyj opcji). -o|--output {LOCATION} Użyj opcji , aby utworzyć folder dla rozwiązania i ustawić przestrzenie nazw projektu rozwiązania. W przykładach tego artykułu rozwiązanie nosi nazwę BlazorHosted (dotnet new blazorwasm -ho -o BlazorHosted).

    W przykładach w tym artykule przestrzeń nazw projektu klienta to BlazorHosted.Client, a przestrzeń nazw projektu serwera to BlazorHosted.Server.

  2. wwwroot/index.html Usuń plik z Blazor WebAssemblyClient projektu.

  3. W projekcie Client usuń następujące wiersze w pliku Program.cs:

    - builder.RootComponents.Add<App>("#app");
    - builder.RootComponents.Add<HeadOutlet>("head::after");
    
  4. Dodaj _Host.cshtml pliki i _Layout.cshtml do Server folderu projektu Pages . Pliki można uzyskać z projektu utworzonego Blazor Server na podstawie szablonu przy użyciu programu Visual Studio lub interfejsu wiersza polecenia platformy .NET za dotnet new blazorserver -o BlazorServer pomocą polecenia w powłoce poleceń ( -o BlazorServer opcja tworzy folder dla projektu). Po umieszczeniu plików w Server folderze projektu Pages wprowadź następujące zmiany w plikach.

    Ważne

    Użycie strony układu (_Layout.cshtml) z pomocnikiem tagów składnika dla HeadOutlet składnika jest wymagane do kontrolowania <head> zawartości, takiej jak tytuł strony (PageTitleskładnik) i inne elementy główne (HeadContent składnik). Aby uzyskać więcej informacji, zobacz Control head content in ASP.NET Core apps (Kontrolowanie zawartości głównej w aplikacjach platformy ASP.NET CoreBlazor).

    Wprowadź następujące zmiany w _Layout.cshtml pliku:

    • Pages Zaktualizuj przestrzeń nazw w górnej części pliku, aby odpowiadała przestrzeni nazw Server stron aplikacji. Symbol {APP NAMESPACE} zastępczy w poniższym przykładzie reprezentuje przestrzeń nazw stron aplikacji dawcy, które dostarczyły _Layout.cshtml pliku:

      Usuwanie:

      - @namespace {APP NAMESPACE}.Pages
      

      Dodaj:

      @namespace BlazorHosted.Server.Pages
      
    • Dodaj dyrektywę @using dla Client projektu w górnej części pliku:

      @using BlazorHosted.Client
      
    • Zaktualizuj łącza arkusza stylów, aby wskazywały arkusze stylów projektu WebAssembly. W poniższym przykładzie przestrzeń nazw projektu klienta to BlazorHosted.Client. Symbol {APP NAMESPACE} zastępczy reprezentuje przestrzeń nazw aplikacji dawcy, która dostarczyła _Layout.cshtml plik. Zaktualizuj pomocnik tagu składnika (<component> tag) dla HeadOutlet składnika, aby wstępnie przygotować składnik.

      Usuwanie:

      - <link href="css/site.css" rel="stylesheet" />
      - <link href="{APP NAMESPACE}.styles.css" rel="stylesheet" />
      - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
      

      Dodaj:

      <link href="css/app.css" rel="stylesheet" />
      <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
      <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
      

      Uwaga

      <link> Pozostaw element, który żąda arkusza stylów Bootstrap (css/bootstrap/bootstrap.min.css) na miejscu.

    • Zaktualizuj źródło skryptu, Blazor aby użyć skryptu po stronie Blazor WebAssembly klienta:

      Usuwanie:

      - <script src="_framework/blazor.server.js"></script>
      

      Dodaj:

      <script src="_framework/blazor.webassembly.js"></script>
      

    W pliku _Host.cshtml:

    • Pages Zmień przestrzeń nazw na tę z Client projektu. Symbol {APP NAMESPACE} zastępczy reprezentuje przestrzeń nazw stron aplikacji dawcy, które dostarczyły _Host.cshtml pliku:

      Usuwanie:

      - @namespace {APP NAMESPACE}.Pages
      

      Dodaj:

      @namespace BlazorHosted.Client
      
    • render-mode Zaktualizuj pomocnik tagu składnika, aby wstępnie wstępnie udostępnić składnik główny App za pomocą polecenia WebAssemblyPrerendered:

      Usuwanie:

      - <component type="typeof(App)" render-mode="ServerPrerendered" />
      

      Dodaj:

      <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
      

      Ważne

      Prerendering nie jest obsługiwany w przypadku punktów końcowych uwierzytelniania (/authentication/ segment ścieżki). Aby uzyskać więcej informacji, zobacz Dodatkowe scenariusze zabezpieczeń zestawu ASP.NET Core Blazor WebAssembly.

  5. W mapowaniu punktu końcowego Server projektu w Program.cspliku zmień rezerwowy z index.html pliku na _Host.cshtml stronę:

    Usuwanie:

    - app.MapFallbackToFile("index.html");
    

    Dodaj:

    app.MapFallbackToPage("/_Host");
    
  6. Jeśli projekty Client i Server używają co najmniej jednej typowej usługi podczas prerenderingu, należy uwzględnić rejestracje usługi w metodzie, którą można wywołać z obu projektów. Aby uzyskać więcej informacji, zobacz ASP.NET Core dependency injection (Wstrzykiwanie zależności ASP.NET CoreBlazor).

  7. Server Uruchom projekt. Blazor WebAssembly Hostowana aplikacja jest wstępnie obsługiwana Server przez projekt dla klientów.

Konfiguracja osadzania Razor składników na stronach lub widokach

Poniższe sekcje i przykłady osadzania Razor składników z ClientBlazor WebAssembly aplikacji na stronach lub widokach aplikacji serwera wymagają dodatkowej konfiguracji.

Projekt Server musi mieć następujące pliki i foldery.

Razor Stron:

  • Pages/Shared/_Layout.cshtml
  • Pages/Shared/_Layout.cshtml.css
  • Pages/_ViewImports.cshtml
  • Pages/_ViewStart.cshtml

MVC:

  • Views/Shared/_Layout.cshtml
  • Views/Shared/_Layout.cshtml.css
  • Views/_ViewImports.cshtml
  • Views/_ViewStart.cshtml

Ważne

Użycie strony układu (_Layout.cshtml) z pomocnikiem tagów składnika dla HeadOutlet składnika jest wymagane do kontrolowania <head> zawartości, takiej jak tytuł strony (PageTitleskładnik) i inne elementy główne (HeadContent składnik). Aby uzyskać więcej informacji, zobacz Control head content in ASP.NET Core apps (Kontrolowanie zawartości głównej w aplikacjach platformy ASP.NET CoreBlazor).

Powyższe pliki można uzyskać, generując aplikację z szablonów projektów platformy ASP.NET Core przy użyciu:

  • Nowe narzędzia do tworzenia projektów programu Visual Studio.
  • Otwieranie powłoki poleceń i wykonywanie dotnet new webapp -o {PROJECT NAME} (Razor Pages) lub dotnet new mvc -o {PROJECT NAME} (MVC). Opcja -o|--output z wartością symbolu zastępczego {PROJECT NAME} zawiera nazwę aplikacji i tworzy folder dla aplikacji.

Zaktualizuj przestrzenie nazw w zaimportowanych _ViewImports.cshtml plikach, aby były zgodne z tymi, które są używane przez Server projekt odbierający pliki.

Pages/_ViewImports.cshtml (Razor Strony):

@using BlazorHosted.Server
@namespace BlazorHosted.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Views/_ViewImports.cshtml (MVC):

@using BlazorHosted.Server
@using BlazorHosted.Server.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Zaktualizuj zaimportowany plik układu, który jest Pages/Shared/_Layout.cshtml przeznaczony dla Razor stron lub Views/Shared/_Layout.cshtml MVC.

Najpierw usuń tytuł i arkusz stylów z projektu darczyńców, który znajduje się RPDonor.styles.css w poniższym przykładzie. Symbol {PROJECT NAME} zastępczy reprezentuje nazwę aplikacji projektu darczyńcy.

- <title>@ViewData["Title"] - {PROJECT NAME}</title>
- <link rel="stylesheet" href="~/RPDonor.styles.css" asp-append-version="true" />

Uwzględnij Client style projektu w pliku układu. W poniższym przykładzie Client przestrzeń nazw projektu to BlazorHosted.Client. Element <title> można zaktualizować w tym samym czasie.

Umieść następujące wiersze w <head> zawartości pliku układu:

<title>@ViewData["Title"] - BlazorHosted</title>
<link href="css/app.css" rel="stylesheet" />
<link rel="stylesheet" href="BlazorHosted.Client.styles.css" asp-append-version="true" />
<component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />

Zaimportowany układ zawiera dwa Home (Index strona) i Privacy linki nawigacji. Aby połączyć Home się z hostowaną Blazor WebAssembly aplikacją, zmień hiperlinki:

- <a class="navbar-brand" asp-area="" asp-page="/Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

W pliku układu MVC:

- <a class="navbar-brand" asp-area="" asp-controller="Home" 
-     asp-action="Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-controller="Home" 
-     asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

<footer> Zaktualizuj nazwę aplikacji elementu. W poniższym przykładzie użyto nazwy BlazorHostedaplikacji :

- &copy; {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ &copy; {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>

W poprzednim przykładzie {DATE} symbol zastępczy reprezentuje datę praw autorskich w aplikacji wygenerowanej Razor na podstawie szablonu projektu Pages lub MVC.

Aby utworzyć Privacy link prowadzący do privacy strony (Razor Strony), dodaj privacy stronę do Server projektu.

Pages/Privacy.cshtml w projekcie Server :

@page
@model PrivacyModel
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

W przypadku widoku opartego na privacy mvC utwórz privacy widok w projekcie Server .

View/Home/Privacy.cshtml w projekcie Server :

@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

W kontrolerze Home aplikacji MVC zwróć widok.

Dodaj następujący kod do pliku Controllers/HomeController.cs:

public IActionResult Privacy()
{
    return View();
}

W przypadku importowania plików z aplikacji darczyńców pamiętaj, aby zaktualizować wszystkie przestrzenie nazw w plikach tak, BlazorHosted.Serveraby pasły Server do tego projektu (na przykład ).

Zaimportuj Server zasoby statyczne do projektu z folderu projektu darczyńców wwwroot :

  • wwwroot/css folder i zawartość
  • wwwroot/js folder i zawartość
  • wwwroot/lib folder i zawartość

Jeśli projekt darczyńcy zostanie utworzony na podstawie szablonu projektu ASP.NET Core i pliki nie zostaną zmodyfikowane, możesz skopiować cały wwwroot folder z projektu darczyńców do Server projektu i usunąć favicon plik ikony.

Ostrzeżenie

Unikaj umieszczania statycznego elementu zawartości w folderach Client i .Server wwwroot Jeśli ten sam plik znajduje się w obu folderach, zgłaszany jest wyjątek, ponieważ statyczny zasób w każdym folderze ma tę samą ścieżkę katalogu głównego sieci Web. W związku z tym hostowanie zasobu statycznego w obu wwwroot folderach, a nie obu.

Po wdrożeniu poprzedniej konfiguracji osadź Razor składniki na stronach lub widokach Server projektu. Skorzystaj ze wskazówek w następujących sekcjach tego artykułu:

  • Renderowanie składników na stronie lub widoku za pomocą pomocnika tagów składników
  • Renderowanie składników na stronie lub widoku za pomocą selektora CSS

Renderowanie składników na stronie lub widoku za pomocą pomocnika tagów składników

Po skonfigurowaniu rozwiązania, w tym dodatkowej konfiguracji, pomocnik tagu składnika obsługuje dwa tryby renderowania składnika do renderowania składnika z Blazor WebAssembly aplikacji na stronie lub widoku:

W poniższym Razor przykładzie Counter strony składnik jest renderowany na stronie. Aby składnik był interaktywny, Blazor WebAssembly skrypt jest zawarty w sekcji renderowania strony. Aby uniknąć używania pełnej przestrzeni nazw składnika Counter z pomocnikiem tagów składników ({ASSEMBLY NAME}.Pages.Counter), dodaj dyrektywę @using dla przestrzeni nazw projektu Pages klienta. W poniższym przykładzie Client przestrzeń nazw projektu to BlazorHosted.Client.

W projekcieServer Pages/RazorPagesCounter1.cshtml:

@page
@using BlazorHosted.Client.Pages

<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Server Uruchom projekt. Przejdź do Razor strony pod adresem /razorpagescounter1. Składnik prerendered Counter jest osadzony na stronie.

RenderMode konfiguruje, czy składnik:

  • Jest wstępnie załadowany do strony.
  • Jest renderowany jako statyczny kod HTML na stronie lub jeśli zawiera informacje niezbędne do uruchomienia Blazor aplikacji z agenta użytkownika.

Aby uzyskać więcej informacji na temat pomocnika tagów składników, w tym przekazywania parametrów i RenderMode konfiguracji, zobacz Pomocnik tagów składników w ASP.NET Core.

W zależności od zasobów statycznych używanych przez składniki i sposobu organizowania stron układu w aplikacji może być wymagana dodatkowa praca. Zazwyczaj skrypty są dodawane do sekcji renderowania Scripts strony lub widoku, a arkusze stylów są dodawane do zawartości elementu układu <head> .

Ustawianie zawartości podrzędnej za pomocą fragmentu renderowania

Pomocnik tagów składników nie obsługuje odbierania delegata RenderFragment dla zawartości podrzędnej (na przykład param-ChildContent="..."). Zalecamy utworzenie Razor składnika (.razor), który odwołuje się do składnika, który ma być renderowany przy użyciu zawartości podrzędnej, którą chcesz przekazać, a następnie wywołania Razor składnika ze strony lub widoku.

Upewnij się, że składniki wstępne najwyższego poziomu nie są przycinane podczas publikowania

Jeśli Pomocnik tagów składników bezpośrednio odwołuje się do składnika z biblioteki, która podlega przycinaniu podczas publikowania, składnik może zostać przycięty podczas publikowania, ponieważ nie ma do niego odwołań z kodu aplikacji po stronie klienta. W związku z tym składnik nie jest wstępnie ustawiony, pozostawiając puste miejsce w danych wyjściowych. W takim przypadku poinstruuj program trimmer, aby zachował składnik biblioteki, dodając DynamicDependency atrybut do dowolnej klasy w aplikacji po stronie klienta. Aby zachować składnik o nazwie SomeLibraryComponentToBePreserved, dodaj następujący element do dowolnego składnika:

@using System.Diagnostics.CodeAnalysis
@attribute [DynamicDependency(DynamicallyAccessedMemberTypes.All, 
    typeof(SomeLibraryComponentToBePreserved))]

Powyższe podejście zwykle nie jest wymagane, ponieważ aplikacja zwykle prerenders jej składniki (które nie są przycinane), co z kolei odwołuje się do składników bibliotek (co powoduje, że nie są one również przycinane). Jawnie używaj DynamicDependency tylko do prerenderingu składnika biblioteki bezpośrednio, gdy biblioteka podlega przycinaniu.

Renderowanie składników na stronie lub widoku za pomocą selektora CSS

Po skonfigurowaniu rozwiązania, w tym dodatkowej konfiguracji, dodaj składniki główne do Client projektu hostowanego Blazor WebAssembly rozwiązania w Program.cs pliku. W poniższym przykładzie Counter składnik jest zadeklarowany jako składnik główny z selektorem CSS, który wybiera element z elementem id counter-componentzgodnym z elementem . W poniższym przykładzie Client przestrzeń nazw projektu to BlazorHosted.Client.

W Program.cs pliku Client projektu dodaj przestrzeń nazw składników projektu Razor na początku pliku:

using BlazorHosted.Client.Pages;

Po ustanowieniu elementu Counter w Program.cselemencie builder dodaj składnik jako składnik główny:

builder.RootComponents.Add<Counter>("#counter-component");

W poniższym Razor przykładzie Counter strony składnik jest renderowany na stronie. Aby składnik był interaktywny, Blazor WebAssembly skrypt jest zawarty w sekcji renderowania strony.

W projekcieServer Pages/RazorPagesCounter2.cshtml:

@page

<div id="counter-component">Loading...</div>

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Server Uruchom projekt. Przejdź do Razor strony pod adresem /razorpagescounter2. Składnik prerendered Counter jest osadzony na stronie.

W zależności od zasobów statycznych używanych przez składniki i sposobu organizowania stron układu w aplikacji może być wymagana dodatkowa praca. Zazwyczaj skrypty są dodawane do sekcji renderowania Scripts strony lub widoku, a arkusze stylów są dodawane do zawartości elementu układu <head> .

Uwaga

Powyższy przykład zgłasza błąd JSException , jeśli Blazor WebAssembly aplikacja jest wstępnie wstępnie wstępnie zintegrowana z aplikacją Razor Pages lub MVC jednocześnie z użyciem selektora CSS. Przejście do jednego ze Client składników projektu Razor lub przejście do strony lub widoku obiektu Server z osadzonym składnikiem zgłasza co najmniej jeden JSExceptionelement .

Jest to normalne zachowanie, ponieważ wstępne tworzenie i integrowanie Blazor WebAssembly aplikacji ze składnikami routingu Razor jest niezgodne z użyciem selektorów CSS.

Jeśli pracujesz z przykładami w poprzednich sekcjach i chcesz zobaczyć, jak selektor CSS działa w przykładowej aplikacji, oznacz specyfikację App składnika Client głównego pliku projektu Program.cs :

- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");

Przejdź do strony lub widoku z osadzonym Razor składnikiem, który używa selektora CSS (na przykład /razorpagescounter2 z poprzedniego przykładu). Strona lub widok są ładowane z osadzonym składnikiem, a osadzony składnik działa zgodnie z oczekiwaniami.

Utrwalanie stanu wstępnego

Bez utrwalania stanu wstępnego, stan używany podczas prerenderingu jest utracony i musi zostać utworzony ponownie, gdy aplikacja jest w pełni załadowana. Jeśli jakikolwiek stan jest skonfigurowany asynchronicznie, interfejs użytkownika może migać, ponieważ wstępnie wypełniony interfejs użytkownika jest zastępowany symbolami zastępczymi tymczasowymi, a następnie w pełni renderowany ponownie.

Aby rozwiązać te problemy, Blazor obsługuje stan utrwalania na stronie wstępnie obsługiwanej przy użyciu pomocnika Tag stanu składnika utrwalania. Dodaj tag Pomocnika tagu , <persist-component-state />wewnątrz tagu zamykającego </body> .

Pages/_Layout.cshtml:

<body>
    ...

    <persist-component-state />
</body>

Zdecyduj, jaki stan ma być trwały przy użyciu PersistentComponentState usługi. PersistentComponentState.RegisterOnPersisting rejestruje wywołanie zwrotne, aby utrwało stan składnika przed wstrzymaniem aplikacji. Stan jest pobierany po wznowieniu działania aplikacji.

Poniższy przykład to zaktualizowana wersja FetchData składnika w hostowanej Blazor WebAssembly aplikacji na podstawie szablonu Blazor projektu. Składnik WeatherForecastPreserveState utrzymuje stan prognozy pogody podczas prerenderingu, a następnie pobiera stan w celu zainicjowania składnika. Pomocnik stanu stanu składnika utrwala stan składnika po wywołaniach wszystkich składników.

Pages/WeatherForecastPreserveState.razor:

@page "/weather-forecast-preserve-state"
@implements IDisposable
@using BlazorSample.Shared
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState

<PageTitle>Weather Forecast</PageTitle>

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = 
            ApplicationState.RegisterOnPersisting(PersistForecasts);

        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            "fetchdata", out var restored))
        {
            forecasts = 
                await WeatherForecastService.GetForecastAsync(DateTime.Now);
        }
        else
        {
            forecasts = restored!;
        }
    }

    private Task PersistForecasts()
    {
        ApplicationState.PersistAsJson("fetchdata", forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

Inicjując składniki o tym samym stanie używanym podczas prerenderingu, wszystkie kosztowne kroki inicjowania są wykonywane tylko raz. Renderowany interfejs użytkownika jest również zgodny ze wstępnie zdefiniowanym interfejsem użytkownika, więc w przeglądarce nie występuje migotanie.

Stan utrwalonego wstępnego jest przenoszony do klienta, gdzie jest używany do przywrócenia stanu składnika. W przypadku wstępnego przetwarzania w aplikacji hostowanej Blazor WebAssembly dane są udostępniane w przeglądarce i nie mogą zawierać poufnych, prywatnych informacji.

Dodatkowe Blazor WebAssembly zasoby

Prerendering może poprawić optymalizację aparatu wyszukiwania (SEO) przez renderowanie zawartości początkowej odpowiedzi HTTP, za pomocą których wyszukiwarki mogą obliczyć rangę strony.

Konfiguracja rozwiązania

Konfiguracja prerenderingu

Aby skonfigurować wstępne ustawianie aplikacji hostowanej Blazor WebAssembly :

  1. Hostowanie Blazor WebAssembly aplikacji w aplikacji ASP.NET Core. Aplikację autonomiczną Blazor WebAssembly można dodać do rozwiązania ASP.NET Core lub użyć hostowanej Blazor WebAssembly aplikacji utworzonej Blazor WebAssembly na podstawie szablonu projektu z opcją hostowaną:

    • Visual Studio: w oknie dialogowym Dodatkowe informacje zaznacz pole wyboru ASP.NET Core Hosted podczas tworzenia Blazor WebAssembly aplikacji. W przykładach tego artykułu rozwiązanie nosi nazwę BlazorHosted.
    • Powłoka poleceń interfejsu -ho|--hosted wiersza polecenia programu Visual Studio Code/.NET: dotnet new blazorwasm -ho (użyj opcji). -o|--output {LOCATION} Użyj opcji , aby utworzyć folder dla rozwiązania i ustawić przestrzenie nazw projektu rozwiązania. W przykładach tego artykułu rozwiązanie nosi nazwę BlazorHosted (dotnet new blazorwasm -ho -o BlazorHosted).

    W przykładach w tym artykule przestrzeń nazw projektu klienta to BlazorHosted.Client, a przestrzeń nazw projektu serwera to BlazorHosted.Server.

  2. wwwroot/index.html Usuń plik z Blazor WebAssemblyClient projektu.

  3. W projekcie Client usuń następujący wiersz w pliku Program.cs:

    - builder.RootComponents.Add<App>("#app");
    
  4. Pages/_Host.cshtml Dodaj plik do Server folderu projektuPages. Plik można uzyskać _Host.cshtml z projektu utworzonego na podstawie Blazor Server szablonu za pomocą dotnet new blazorserver -o BlazorServer polecenia w powłoce poleceń ( -o BlazorServer opcja tworzy folder dla projektu). Po umieszczeniu pliku w Pages/_Host.cshtml Server projekcie hostowanego Blazor WebAssembly rozwiązania wprowadź następujące zmiany w pliku:

    • Podaj dyrektywę @using dla Client projektu (na przykład @using BlazorHosted.Client).

    • Zaktualizuj łącza arkusza stylów, aby wskazywały arkusze stylów projektu WebAssembly. W poniższym przykładzie przestrzeń nazw projektu klienta to BlazorHosted.Client:

      - <link href="css/site.css" rel="stylesheet" />
      - <link href="_content/BlazorServer/_framework/scoped.styles.css" rel="stylesheet" />
      + <link href="css/app.css" rel="stylesheet" />
      + <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
      

      Uwaga

      <link> Pozostaw element, który żąda arkusza stylów Bootstrap (css/bootstrap/bootstrap.min.css) na miejscu.

    • render-mode Zaktualizuj pomocnik tagu składnika, aby wstępnie wstępnie udostępnić składnik główny App za pomocą polecenia WebAssemblyPrerendered:

      - <component type="typeof(App)" render-mode="ServerPrerendered" />
      + <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
      
    • Zaktualizuj źródło skryptu, Blazor aby użyć skryptu po stronie Blazor WebAssembly klienta:

      - <script src="_framework/blazor.server.js"></script>
      + <script src="_framework/blazor.webassembly.js"></script>
      
  5. W Startup.Configure projekcie Server zmień rezerwowy index.html z pliku na _Host.cshtml stronę.

    Startup.cs:

    - endpoints.MapFallbackToFile("index.html");
    + endpoints.MapFallbackToPage("/_Host");
    
  6. Jeśli projekty Client i Server używają co najmniej jednej typowej usługi podczas prerenderingu, należy uwzględnić rejestracje usługi w metodzie, którą można wywołać z obu projektów. Aby uzyskać więcej informacji, zobacz ASP.NET Core dependency injection (Wstrzykiwanie zależności ASP.NET CoreBlazor).

  7. Server Uruchom projekt. Blazor WebAssembly Hostowana aplikacja jest wstępnie obsługiwana Server przez projekt dla klientów.

Konfiguracja osadzania Razor składników na stronach lub widokach

Poniższe sekcje i przykłady w tym artykule dotyczące osadzania Razor składników aplikacji klienckiej Blazor WebAssembly na stronach lub widokach aplikacji serwera wymagają dodatkowej konfiguracji.

Użyj domyślnego Razor pliku stron lub układu MVC w projekcie Server . Projekt Server musi mieć następujące pliki i foldery.

Razor Stron:

  • Pages/Shared/_Layout.cshtml
  • Pages/_ViewImports.cshtml
  • Pages/_ViewStart.cshtml

MVC:

  • Views/Shared/_Layout.cshtml
  • Views/_ViewImports.cshtml
  • Views/_ViewStart.cshtml

Uzyskaj powyższe pliki z aplikacji utworzonej na podstawie szablonu Razor projektu Pages lub MVC. Aby uzyskać więcej informacji, zobacz Samouczek: rozpoczynanie pracy ze stronami Razor w ASP.NET Core lub Rozpoczynanie pracy z ASP.NET Core MVC.

Zaktualizuj przestrzenie nazw w zaimportowanych _ViewImports.cshtml plikach, aby były zgodne z tymi, które są używane przez Server projekt odbierający pliki.

Zaktualizuj zaimportowany plik układu (_Layout.cshtml), aby uwzględnić Client style projektu. W poniższym przykładzie Client przestrzeń nazw projektu to BlazorHosted.Client. Element <title> można zaktualizować w tym samym czasie.

Pages/Shared/_Layout.cshtml (Razor Pages) lub Views/Shared/_Layout.cshtml (MVC):

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-   <title>@ViewData["Title"] - DonorProject</title>
+   <title>@ViewData["Title"] - BlazorHosted</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
+   <link href="css/app.css" rel="stylesheet" />
+   <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
</head>

Zaimportowany układ zawiera Home linki nawigacji i Privacy . Aby utworzyć Home punkt połączenia z hostowaną Blazor WebAssembly aplikacją, zmień hiperlink:

- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

W pliku układu MVC:

- <a class="nav-link text-dark" asp-area="" asp-controller="Home" 
-     asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

Aby utworzyć Privacy link prowadzący do privacy strony, dodaj privacy stronę do Server projektu.

Pages/Privacy.cshtml w projekcie Server :

@page
@model BlazorHosted.Server.Pages.PrivacyModel
@{
}

<h1>Privacy Policy</h1>

Jeśli preferowany jest widok oparty na privacy mvC, utwórz privacy widok w projekcie Server .

View/Home/Privacy.cshtml:

@{
    ViewData["Title"] = "Privacy Policy";
}

<h1>@ViewData["Title"]</h1>

W kontrolerze Home zwróć widok.

Controllers/HomeController.cs:

public IActionResult Privacy()
{
    return View();
}

Zaimportuj Server zasoby statyczne do projektu z folderu projektu darczyńców wwwroot :

  • wwwroot/css folder i zawartość
  • wwwroot/js folder i zawartość
  • wwwroot/lib folder i zawartość

Jeśli projekt darczyńcy zostanie utworzony na podstawie szablonu projektu ASP.NET Core i pliki nie zostaną zmodyfikowane, możesz skopiować cały wwwroot folder z projektu darczyńców do Server projektu i usunąć favicon plik ikony.

Ostrzeżenie

Unikaj umieszczania statycznego elementu zawartości w folderach Client i .Server wwwroot Jeśli ten sam plik znajduje się w obu folderach, zgłaszany jest wyjątek, ponieważ statyczny zasób w każdym folderze ma tę samą ścieżkę katalogu głównego sieci Web. W związku z tym hostowanie zasobu statycznego w obu wwwroot folderach, a nie obu.

Renderowanie składników na stronie lub widoku za pomocą pomocnika tagów składników

Po skonfigurowaniu rozwiązania, w tym dodatkowej konfiguracji, pomocnik tagu składnika obsługuje dwa tryby renderowania składnika do renderowania składnika z Blazor WebAssembly aplikacji na stronie lub widoku:

W poniższym Razor przykładzie Counter strony składnik jest renderowany na stronie. Aby składnik był interaktywny, Blazor WebAssembly skrypt jest zawarty w sekcji renderowania strony. Aby uniknąć używania pełnej przestrzeni nazw składnika Counter z pomocnikiem tagów składników ({ASSEMBLY NAME}.Pages.Counter), dodaj dyrektywę @using dla przestrzeni nazw projektu Pages klienta. W poniższym przykładzie Client przestrzeń nazw projektu to BlazorHosted.Client.

W projekcieServer Pages/RazorPagesCounter1.cshtml:

@page
@using BlazorHosted.Client.Pages

<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Server Uruchom projekt. Przejdź do Razor strony pod adresem /razorpagescounter1. Składnik prerendered Counter jest osadzony na stronie.

RenderMode konfiguruje, czy składnik:

  • Jest wstępnie załadowany do strony.
  • Jest renderowany jako statyczny kod HTML na stronie lub jeśli zawiera informacje niezbędne do uruchomienia Blazor aplikacji z agenta użytkownika.

Aby uzyskać więcej informacji na temat pomocnika tagów składników, w tym przekazywania parametrów i RenderMode konfiguracji, zobacz Pomocnik tagów składników w ASP.NET Core.

W zależności od zasobów statycznych używanych przez składniki i sposobu organizowania stron układu w aplikacji może być wymagana dodatkowa praca. Zazwyczaj skrypty są dodawane do sekcji renderowania Scripts strony lub widoku, a arkusze stylów są dodawane do zawartości elementu układu <head> .

Renderowanie składników na stronie lub widoku za pomocą selektora CSS

Po skonfigurowaniu rozwiązania, w tym dodatkowej konfiguracji, dodaj składniki główne do Client projektu hostowanego Blazor WebAssembly rozwiązania w programie Program.cs. W poniższym przykładzie Counter składnik jest zadeklarowany jako składnik główny z selektorem CSS, który wybiera element z elementem id counter-componentzgodnym z elementem . W poniższym przykładzie Client przestrzeń nazw projektu to BlazorHosted.Client.

W Program.cs projekcie Client dodaj przestrzeń nazw składników projektu Razor na początku pliku:

using BlazorHosted.Client.Pages;

Po ustanowieniu elementu Counter w Program.cselemencie builder dodaj składnik jako składnik główny:

builder.RootComponents.Add<Counter>("#counter-component");

W poniższym Razor przykładzie Counter strony składnik jest renderowany na stronie. Aby składnik był interaktywny, Blazor WebAssembly skrypt jest zawarty w sekcji renderowania strony.

W projekcieServer Pages/RazorPagesCounter2.cshtml:

@page

<div id="counter-component">Loading...</div>

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Server Uruchom projekt. Przejdź do Razor strony pod adresem /razorpagescounter2. Składnik prerendered Counter jest osadzony na stronie.

W zależności od zasobów statycznych używanych przez składniki i sposobu organizowania stron układu w aplikacji może być wymagana dodatkowa praca. Zazwyczaj skrypty są dodawane do sekcji renderowania Scripts strony lub widoku, a arkusze stylów są dodawane do zawartości elementu układu <head> .

Uwaga

Powyższy przykład zgłasza błąd JSException , jeśli Blazor WebAssembly aplikacja jest wstępnie wstępnie wstępnie zintegrowana z aplikacją Razor Pages lub MVC jednocześnie z selektorem CSS. Przejście do jednego ze Client składników projektu Razor zgłasza następujący wyjątek:

Microsoft.JSInterop.JSException: Nie można odnaleźć żadnego elementu pasującego selektora "#counter-component".

Jest to normalne zachowanie, ponieważ wstępne tworzenie i integrowanie Blazor WebAssembly aplikacji ze składnikami routingu Razor jest niezgodne z użyciem selektorów CSS.

Dodatkowe Blazor WebAssembly zasoby

Integrowanie Razor składników ze Razor stronami lub aplikacjami MVC w hostowanymBlazor WebAssembly rozwiązaniu jest obsługiwane w programie ASP.NET Core na platformie .NET 5 lub nowszym. Wybierz platformę .NET 5 lub nowszą wersję tego artykułu.