режимы отрисовки ASP.NET Core Blazor

В этой статье объясняется управление отрисовкой компонентов в Blazor веб-приложения во время компиляции Razor или во время выполнения.

Это руководство не относится к автономным Blazor WebAssembly приложениям. Blazor WebAssemblyприложения отображаются только на клиенте с помощью клиентской среды выполнения WebAssembly и не имеют концепции режима отрисовки. Если режим отрисовки применяется к компоненту в Blazor WebAssembly приложении, назначение режима отрисовки не влияет на отрисовку компонента.

Режимы отрисовки

Каждый компонент в Blazor веб-приложении принимает режим отрисовки, чтобы определить модель размещения, которую он использует, где она отрисовывается, и независимо от того, является ли она интерактивной.

В следующей Blazor таблице показаны доступные режимы отрисовки компонентов отрисовки Razor в веб-приложении. Чтобы применить режим отрисовки к компоненту, используйте @rendermode директиву для экземпляра компонента или определения компонента. Далее в этой статье показаны примеры для каждого сценария режима отрисовки.

Имя Описание Расположение отрисовки Интерактивный
Статический сервер Статическое отрисовка на стороне сервера (статический SSR) Сервер Нет
Интерактивный сервер Интерактивная отрисовка на стороне сервера (интерактивная среда SSR) с помощью Blazor Server. Сервер Да
Интерактивный webAssembly Отрисовка на стороне клиента (CSR) с помощью Blazor WebAssembly†. Клиент Да
Интерактивное авто Интерактивная служба SSR, используемая Blazor Server изначально, а затем CSR при последующих посещениях после Blazor скачивания пакета. Сервер, а затем клиент Да

†Клиентская отрисовка (CSR) считается интерактивной. "Интерактивная отрисовка на стороне клиента" и "интерактивная CSR" не используются в отрасли или в Blazor документации.

Предварительная подготовка включена по умолчанию для интерактивных компонентов. Инструкции по управлению предварительной подготовкой приведены далее в этой статье. Общие отраслевые терминологии в концепциях отрисовки клиентов и серверов см. в ASP.NET основных Blazor принципах.

В следующих примерах демонстрируется настройка режима отрисовки компонента с помощью нескольких основных Razor компонентов.

Чтобы протестировать поведение режима отрисовки локально, можно разместить следующие компоненты в приложении, созданном Blazor на основе шаблона проекта веб-приложения . При создании приложения выберите параметры в раскрывающихся меню (Visual Studio) или примените параметры ИНТЕРФЕЙСА командной строки (.NET CLI), чтобы включить взаимодействие на стороне сервера и на стороне клиента. Инструкции по созданию Blazor веб-приложения см. в разделе "Инструменты для ASP.NET Core Blazor".

Включение поддержки интерактивных режимов отрисовки

Blazor Веб-приложение должно быть настроено для поддержки интерактивных режимов отрисовки. Следующие расширения автоматически применяются к приложениям, созданным из Blazor шаблона проекта веб-приложения во время создания приложения. Отдельные компоненты по-прежнему необходимы для объявления режима отрисовки в разделе режимов отрисовки после настройки служб компонентов и конечных точек в файле приложения Program .

Службы для Razor компонентов добавляются путем вызова AddRazorComponents.

Расширения построителя компонентов:

  • AddInteractiveServerComponents добавляет службы для поддержки отрисовки компонентов интерактивного сервера.
  • AddInteractiveWebAssemblyComponents добавляет службы для поддержки отрисовки компонентов Interactive WebAssembly.

MapRazorComponents обнаруживает доступные компоненты и задает корневой компонент для приложения (первый загруженный компонент), который по умолчанию является компонентом App (App.razor).

Расширения построителя соглашений конечной точки:

  • AddInteractiveServerRenderMode настраивает интерактивную отрисовку на стороне сервера (интерактивная служба SSR) для приложения.
  • AddInteractiveWebAssemblyRenderMode настраивает режим отрисовки интерактивного веб-сайта для приложения.

Примечание.

Для ориентации на размещение API в следующих примерах проверьте Program файл приложения, созданного на Blazor основе шаблона проекта веб-приложения. Инструкции по созданию Blazor веб-приложения см. в разделе "Инструменты для ASP.NET Core Blazor".

Пример 1. Следующий Program API файлов добавляет службы и конфигурацию для включения интерактивного SSR:

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

Пример 2. Следующий Program API файлов добавляет службы и конфигурацию для включения режима интерактивной отрисовки WebAssembly:

builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents();
app.MapRazorComponents<App>()
    .AddInteractiveWebAssemblyRenderMode();

Пример 3. Следующий Program API файлов добавляет службы и конфигурацию для включения режима интерактивного сервера, интерактивного веб-сайта и интерактивного автоматического отрисовки:

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode();

BlazorBlazor WebAssembly использует модель размещения для скачивания и выполнения компонентов, использующих режим интерактивной отрисовки WebAssembly. Для настройки Blazor WebAssembly размещения этих компонентов требуется отдельный клиентский проект. Клиентский проект содержит код запуска узла Blazor WebAssembly и настраивает среду выполнения .NET для запуска в браузере. Шаблон Blazor веб-приложения добавляет этот клиентский проект для вас при выборе параметра для включения интерактивности WebAssembly. Все компоненты, использующие режим интерактивной отрисовки WebAssembly, должны быть созданы из клиентского проекта, поэтому они включаются в скачанный пакет приложений.

Применение режима отрисовки к экземпляру компонента

Чтобы применить режим отрисовки к экземпляру компонента, используйте @rendermodeRazor атрибут директивы, в котором используется компонент.

В следующем примере к экземпляру Dialog компонента применяется интерактивная отрисовка на стороне сервера (интерактивная служба SSR):

<Dialog @rendermode="InteractiveServer" />

Примечание.

Blazor шаблоны включают статическую using директиву для RenderMode файла приложения _Imports (Components/_Imports.razor) для более @rendermode короткого синтаксиса:

@using static Microsoft.AspNetCore.Components.Web.RenderMode

Без предыдущей директивы компоненты должны указывать статический RenderMode класс в @rendermode синтаксисе:

<Dialog @rendermode="RenderMode.InteractiveServer" />

Можно также ссылаться на экземпляры пользовательского режима отрисовки, созданные непосредственно с пользовательской конфигурацией. Дополнительные сведения см . в разделе "Пользовательские режимы отрисовки " далее в этой статье.

Применение режима отрисовки к определению компонента

Чтобы указать режим отрисовки для компонента в рамках его определения, используйте @rendermodeRazor директиву и соответствующий атрибут режима отрисовки.

@page "..."
@rendermode InteractiveServer

Применение режима отрисовки к определению компонента обычно используется при применении режима отрисовки к определенной странице. По умолчанию routable pages использует тот же режим отрисовки, что Router и компонент, отрисованный на странице.

@rendermode Технически это директиваRazorи Razorатрибут директивы. Семантика аналогична, но существуют различия. Директива @rendermode находится в определении компонента, поэтому экземпляр режима отрисовки, на который ссылается, должен быть статическим. Атрибут директивы может принимать любой @rendermode экземпляр режима отрисовки.

Примечание.

Авторы компонентов должны избегать связывания реализации компонента с определенным режимом отрисовки. Вместо этого авторы компонентов обычно должны разрабатывать компоненты для поддержки любого режима отрисовки или модели размещения. Реализация компонента должна избежать предположений о том, где она работает (сервер или клиент) и должна ухудшаться корректно при отображении статически. Указание режима отрисовки в определении компонента может потребоваться, если компонент не создается непосредственно (например, с компонентом routable page) или указать режим отрисовки для всех экземпляров компонентов.

Применение режима отрисовки ко всему приложению

Чтобы задать режим отрисовки для всего приложения, укажите режим отрисовки на самом высоком уровне интерактивного компонента в иерархии компонентов приложения, который не является корневым компонентом.

Примечание.

Создание интерактивного корневого компонента, например App компонента, не поддерживается. Поэтому режим отрисовки для всего приложения не может быть задан непосредственно компонентом App .

Для приложений на Blazor основе шаблона проекта веб-приложения режим отрисовки, назначенный всему приложению, обычно указывается, где Routes компонент используется в App компоненте (Components/App.razor):

<Routes @rendermode="InteractiveServer" />

Компонент Router распространяет режим отрисовки на страницы, на которые он направляется.

Кроме того, обычно необходимо задать тот же интерактивный режим отрисовки компонентаHeadOutlet, который также находится в App компоненте Blazor веб-приложения, созданном на основе шаблона проекта:

<HeadOutlet @rendermode="InteractiveServer" />

Для приложений, которые принимают интерактивный клиентский режим (WebAssembly или auto) отрисовки и включите режим отрисовки Routes для всего приложения через компонент:

  • Поместите или переместите файлы макета и навигации папки приложения Components/Layout сервера в папку .Client проекта Layout . Создайте папку Layout.Client в проекте, если она не существует.
  • Поместите или переместите компоненты папки серверного приложения Components/Pages в папку .Client проекта Pages . Создайте папку Pages.Client в проекте, если она не существует.
  • Поместите или переместите Routes компонент папки приложения Components сервера в .Client корневую папку проекта.

Чтобы включить глобальную Blazor интерактивность при создании веб-приложения:

  • Visual Studio: задайте раскрывающийся список расположений интерактивного взаимодействия в глобальном списке.
  • .NET CLI: используйте -ai|--all-interactive этот параметр.

Дополнительные сведения см. в статье Инструментарий для ASP.NET Core Blazor.

Применение режима отрисовки программно

Свойства и поля могут назначать режим отрисовки.

Второй подход, описанный в этом разделе, задание режима отрисовки экземпляром компонента особенно полезно, если спецификация приложения вызывает любой из следующих сценариев:

  • У вас есть область (папка) приложения с компонентами, которые должны принимать статическую отрисовку на стороне сервера (статический SSR) и запускаться только на сервере. Приложение управляет режимом отрисовки глобально, задав режим отрисовки компонента Routes в App компоненте на основе пути к папке.
  • У вас есть компоненты вокруг приложения в различных расположениях (не в одной папке), которые должны принимать статический SSR и запускаться только на сервере. Приложение управляет режимом отрисовки на основе каждого компонента, задав режим отрисовки директивой @rendermode в экземплярах компонентов. Рефлексия используется в компоненте App для задания режима отрисовки Routes компонента.

В обоих случаях компонент, который должен принимать статический SSR, также должен принудительно перезагрузить полную страницу.

Предыдущие два сценария рассматриваются в примерах в разделе "Точное управление режимами отрисовки" далее в этой статье. В следующих двух подразделах рассматриваются основные подходы к настройке режима отрисовки.

Настройка режима отрисовки по определению компонента

Определение компонента может определять режим отрисовки через частное поле:

@rendermode renderModeForPage

...

@code {
    private static IComponentRenderMode renderModeForPage = InteractiveServer;
}

Настройка режима отрисовки по экземпляру компонента

В следующем примере к любому запросу применяется интерактивная отрисовка на стороне сервера (интерактивная служба SSR).

<Routes @rendermode="RenderModeForPage" />

...

@code {
    private IComponentRenderMode? RenderModeForPage => InteractiveServer;
}

Дополнительные сведения о распространении режима отрисовки приведены в разделе распространения режима отрисовки далее в этой статье. В разделе "Точный контроль режимов отрисовки" показано, как использовать предыдущий подход для внедрения статического SSR в определенных областях приложения (папок) или для определенных компонентов, распространяемых вокруг приложения с назначениями режима отрисовки для каждого компонента.

Предварительная отрисовка

Предварительная отрисовка — это процесс первоначальной отрисовки содержимого страницы на сервере без включения обработчиков событий для отрисованных элементов управления. Сервер выводит HTML-интерфейс страницы как можно скорее в ответ на первоначальный запрос, что делает приложение более адаптивным к пользователям. Предварительная подготовка также может улучшить оптимизацию поисковой системы (SEO), отрисовав содержимое для первоначального HTTP-ответа, используемого поисковыми системами для вычисления ранжирования страниц.

Предварительная подготовка включена по умолчанию для интерактивных компонентов.

Чтобы отключить предварительную отрисовку для экземпляра компонента, передайте prerender флаг со значением false режима отрисовки:

  • <... @rendermode="new InteractiveServerRenderMode(prerender: false)" />
  • <... @rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)" />
  • <... @rendermode="new InteractiveAutoRenderMode(prerender: false)" />

Чтобы отключить предварительную отрисовку в определении компонента, выполните следующие действия.

  • @rendermode @(new InteractiveServerRenderMode(prerender: false))
  • @rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
  • @rendermode @(new InteractiveAutoRenderMode(prerender: false))

Чтобы отключить предварительную отрисовку для всего приложения, укажите режим отрисовки на самом высоком уровне интерактивного компонента в иерархии компонентов приложения, которая не является корневым компонентом.

Для приложений на Blazor основе шаблона проекта веб-приложения режим отрисовки, назначенный всему приложению, указывается, где Routes компонент используется в App компоненте (Components/App.razor). В следующем примере для режима отрисовки приложения устанавливается интерактивный сервер с отключенным предопределенным отображением:

<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />

Кроме того, отключите предварительную отрисовку компонента HeadOutlet в компоненте:App

<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />

Создание корневого компонента, например App компонента, интерактивного с @rendermode директивой в верхней части файла определения корневого компонента (.razor) не поддерживается. Поэтому предварительная подготовка не может быть отключена непосредственно компонентом App .

Статическое отрисовка на стороне сервера (статический SSR)

По умолчанию компоненты используют статическую отрисовку на стороне сервера (статический SSR). Компонент отрисовывается в поток отклика и интерактивность не включена.

В следующем примере нет обозначения режима отрисовки компонента, поэтому компонент наследует его режим отрисовки от родительского элемента. Так как компонент предка не указывает режим отрисовки, следующий компонент статически отрисовывается на сервере. Кнопка не является интерактивной и не вызывает метод при выборе UpdateMessage . Значение message не изменяется, и компонент не переназначется в ответ на события пользовательского интерфейса.

RenderMode1.razor:

@page "/render-mode-1"

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not updated yet.";

    private void UpdateMessage()
    {
        message = "Somebody updated me!";
    }
}

При использовании предыдущего компонента локально в Blazor веб-приложении поместите компонент в папку проекта Components/Pages сервера. Серверный проект — это проект решения с именем, который не заканчивается .Client. При запуске приложения перейдите /render-mode-1 в адресную строку браузера.

Во время статического SSR Razor запросы страниц компонента обрабатываются серверным ASP.NET обработкой запросов конвейера по промежуточного слоя Core для маршрутизации и авторизации. Выделенные Blazor функции маршрутизации и авторизации не работают, так как Razor компоненты не отображаются во время обработки запросов на стороне сервера. Blazor функции маршрутизатора в компоненте Routes , недоступном во время статического SSR, включают отображение:

Если приложение демонстрирует интерактивность корневого уровня, обработка запросов на стороне сервера ASP.NET Core не участвует после первоначального статического SSR, что означает, что предыдущие Blazor функции работают должным образом.

Улучшенная навигация со статическим SSR требует особого внимания при загрузке JavaScript. Дополнительные сведения см. в разделе ASP.NET Core Blazor JavaScript со статическим отображением на стороне сервера (статический SSR).

Интерактивная отрисовка на стороне сервера (интерактивная среда SSR)

Интерактивная отрисовка на стороне сервера (интерактивная служба SSR) отображает компонент интерактивным образом с сервера.Blazor Server Взаимодействие с пользователем обрабатывается через подключение в режиме реального времени с браузером. Подключение к каналу устанавливается при отрисовки компонента сервера.

В следующем примере режим отрисовки устанавливается интерактивный SSR путем добавления @rendermode InteractiveServer в определение компонента. Кнопка вызывает UpdateMessage метод при выборе. Значение message изменений и компонент переназначен для обновления сообщения в пользовательском интерфейсе.

RenderMode2.razor:

@page "/render-mode-2"
@rendermode InteractiveServer

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not updated yet.";

    private void UpdateMessage()
    {
        message = "Somebody updated me!";
    }
}

При использовании предыдущего компонента локально в Blazor веб-приложении поместите компонент в папку проекта Components/Pages сервера. Серверный проект — это проект решения с именем, который не заканчивается .Client. При запуске приложения перейдите /render-mode-2 в адресную строку браузера.

Отрисовка на стороне клиента (CSR)

Отрисовка на стороне клиента (CSR) обрабатывает компонент интерактивным образом Blazor WebAssemblyна клиенте. Среда выполнения .NET и пакет приложений загружаются и кэшируются при первоначальном отображении компонента WebAssembly. Компоненты, использующие CSR, должны быть созданы из отдельного клиентского Blazor WebAssembly проекта, который настраивает узел.

В следующем примере режим отрисовки имеет значение CSR с @rendermode InteractiveWebAssembly. Кнопка вызывает UpdateMessage метод при выборе. Значение message изменений и компонент переназначен для обновления сообщения в пользовательском интерфейсе.

RenderMode3.razor:

@page "/render-mode-3"
@rendermode InteractiveWebAssembly

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not updated yet.";

    private void UpdateMessage()
    {
        message = "Somebody updated me!";
    }
}

При использовании предыдущего компонента локально в Blazor веб-приложении поместите компонент в папку клиентского проекта Pages . Клиентский проект — это проект решения с именем, который заканчивается .Client. При запуске приложения перейдите /render-mode-3 в адресную строку браузера.

Автоматическая отрисовка (авто)

Автоматическая отрисовка (авто) определяет способ отрисовки компонента во время выполнения. Компонент изначально отрисовывается с помощью интерактивной отрисовки на стороне сервера (интерактивная служба SSR) с помощью Blazor Server модели размещения. Среда выполнения .NET и пакет приложений загружаются на клиент в фоновом режиме и кэшируются, чтобы их можно было использовать в будущих визитах.

Режим автоматической отрисовки никогда динамически не изменяет режим отрисовки компонента, уже на странице. Режим автоматической отрисовки принимает первоначальное решение о том, какой тип взаимодействия будет использоваться для компонента, а затем компонент сохраняет этот тип интерактивности до тех пор, пока он находится на странице. Одним из факторов в этом первоначальном решении является рассмотрение того, существуют ли компоненты на странице с интерактивностью WebAssembly/Server. Автоматический режим предпочитает выбрать режим отрисовки, соответствующий режиму отрисовки существующих интерактивных компонентов. Причина, по которой автоматический режим предпочитает использовать существующий режим интерактивного взаимодействия, заключается в том, чтобы избежать внедрения новой интерактивной среды выполнения, которая не предоставляет общий доступ к состоянию существующей среды выполнения.

Компоненты, использующие режим автоматической отрисовки, должны быть созданы из отдельного клиентского Blazor WebAssembly проекта, который настраивает узел.

В следующем примере компонент является интерактивным во время процесса. Кнопка вызывает UpdateMessage метод при выборе. Значение message изменений и компонент переназначен для обновления сообщения в пользовательском интерфейсе. Изначально компонент отображается в интерактивном режиме с сервера, но при последующих посещениях он отрисовывается от клиента после скачивания и кэширования пакета приложений .NET.

RenderMode4.razor:

@page "/render-mode-4"
@rendermode InteractiveAuto

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not updated yet.";

    private void UpdateMessage()
    {
        message = "Somebody updated me!";
    }
}

При использовании предыдущего компонента локально в Blazor веб-приложении поместите компонент в папку клиентского проекта Pages . Клиентский проект — это проект решения с именем, который заканчивается .Client. При запуске приложения перейдите /render-mode-4 в адресную строку браузера.

Распространение режима отрисовки

Режимы отрисовки распространяются вниз иерархии компонентов.

Правила применения режимов отрисовки:

  • Режим отрисовки по умолчанию является статическим.
  • Интерактивный сервер (InteractiveServer), интерактивный webAssembly (InteractiveWebAssemblyInteractiveAuto) и режимы интерактивного автообрисовки () можно использовать из компонента, включая использование различных режимов отрисовки для компонентов-одноуровневых компонентов.
  • Невозможно переключиться на другой интерактивный режим отрисовки в дочернем компоненте. Например, компонент сервера не может быть дочерним компонентом WebAssembly.
  • Параметры, передаваемые интерактивному дочернему компоненту из статического родительского элемента, должны быть JSсериализуемыми в ON. Это означает, что невозможно передать фрагменты отрисовки или дочернее содержимое из статического родительского компонента в интерактивный дочерний компонент.

В следующих примерах используется неизменяемый, нестраничный SharedMessage компонент. Не зависящий SharedMessage от режима отрисовки компонент не применяет режим отрисовки с директивой@attribute. Если вы тестируете эти сценарии с Blazor помощью веб-приложения, поместите следующий компонент в папку приложения Components .

SharedMessage.razor:

<p>@Greeting</p>

<button @onclick="UpdateMessage">Click me</button> @message

<p>@ChildContent</p>

@code {
    private string message = "Not updated yet.";

    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    [Parameter]
    public string Greeting { get; set; } = "Hello!";

    private void UpdateMessage()
    {
        message = "Somebody updated me!";
    }
}

Наследование режима отрисовки

SharedMessage Если компонент помещается в статически отрисованный родительский компонент, SharedMessage компонент также отображается статически и не является интерактивным. Кнопка не вызывается UpdateMessage, и сообщение не обновляется.

RenderMode5.razor:

@page "/render-mode-5"

<SharedMessage />

SharedMessage Если компонент помещается в компонент, определяющий режим отрисовки, он наследует примененный режим отрисовки.

В следующем примере SharedMessage компонент является интерактивным SignalR через подключение к клиенту. Вызовы UpdateMessageкнопки и обновление сообщения.

RenderMode6.razor:

@page "/render-mode-6"
@rendermode InteractiveServer

<SharedMessage />

Дочерние компоненты с различными режимами отрисовки

В следующем примере оба SharedMessage компонента предварительно отображаются (по умолчанию) и отображаются при отображении страницы в браузере.

  • Первый SharedMessage компонент с интерактивной отрисовкой на стороне сервера (интерактивный SSR) является интерактивным после SignalR установки канала.
  • Второй SharedMessage компонент с отрисовкой на стороне клиента (CSR) является интерактивным послеBlazor скачивания пакета приложений, а среда выполнения .NET активна на клиенте.

RenderMode7.razor:

@page "/render-mode-7"

<SharedMessage @rendermode="InteractiveServer" />
<SharedMessage @rendermode="InteractiveWebAssembly" />

Дочерний компонент с сериализуемым параметром

В следующем примере показан интерактивный дочерний компонент, который принимает параметр. Параметры должны быть сериализуемыми.

RenderMode8.razor:

@page "/render-mode-8"

<SharedMessage @rendermode="InteractiveServer" Greeting="Welcome!" />

Несериализируемые параметры компонента, такие как дочернее содержимое или фрагмент отрисовки, не поддерживаются. В следующем примере передача дочернего содержимого SharedMessage компоненту приводит к ошибке среды выполнения.

RenderMode9.razor:

@page "/render-mode-9"

<SharedMessage @rendermode="InteractiveServer">
    Child content
</SharedMessage>

Ошибка.

System.InvalidOperationException: не удается передать параметр ChildContent компоненту SharedMessage с rendermode "InteractiveServerRenderMode". Это связано с тем, что параметр имеет тип делегата Microsoft.AspNetCore.Components.RenderFragment, который является произвольным кодом и не может быть сериализован.

Чтобы обойти предыдущее ограничение, заключите дочерний компонент в другой компонент, который не имеет параметра. Это подход, принятый в Blazor шаблоне проекта веб-приложения с компонентом Routes (Components/Routes.razor) для упаковки Router компонента.

WrapperComponent.razor:

<SharedMessage>
    Child content
</SharedMessage>

RenderMode10.razor:

@page "/render-mode-10"

<WrapperComponent @rendermode="InteractiveServer" />

В предыдущем примере:

  • Дочернее содержимое передается SharedMessage компоненту без возникновения ошибки среды выполнения.
  • Компонент SharedMessage отображается в интерактивном режиме на сервере.

Дочерний компонент с другим режимом отрисовки, отличным от родительского

Не пытайтесь применить другой интерактивный режим отрисовки к дочернему компоненту, отличному от режима отрисовки родительского элемента.

Следующий компонент приводит к ошибке среды выполнения при отрисовке компонента:

RenderMode11.razor:

@page "/render-mode-11"
@rendermode InteractiveServer

<SharedMessage @rendermode="InteractiveWebAssembly" />

Ошибка.

Cannot create a component of type 'BlazorSample.Components.SharedMessage' because its render mode 'Microsoft.AspNetCore.Components.Web.InteractiveWebAssemblyRenderMode' is not supported by Interactive Server rendering.

Точное управление режимами отрисовки

Существуют случаи, когда спецификация приложения вызывает компоненты для внедрения статической отрисовки на стороне сервера (статический SSR) и запускается только на сервере, а остальная часть приложения использует интерактивный режим отрисовки.

Существует два подхода, которые можно использовать для точного контроля режимов отрисовки, каждый из которых описан в следующих подразделах:

В обоих случаях компонент, который должен принимать статический SSR, также должен принудительно перезагрузить полную страницу.

В следующих примерах HttpContext используется каскадный параметр, чтобы определить, является ли страница статической отрисовки. Указывает nullHttpContext , что компонент отображается в интерактивном режиме, что полезно в качестве сигнала в коде приложения для активации полностраничной перезагрузки.

Область (папка) статических компонентов SSR

Подход, описанный в этом подразделе, используется шаблоном Blazor проекта веб-приложения с индивидуальной проверкой подлинности и глобальным взаимодействием.

Область (папка) приложения содержит компоненты, которые должны принимать статический SSR и запускаться только на сервере. Компоненты в папке используют один и тот же префикс пути маршрута. Например, IdentityRazor компоненты Blazor шаблона проекта веб-приложения находятся в папке Components/Account/Pages и предоставляют общий доступ к префиксу /Accountкорневого пути.

Папка также содержит _Imports.razor файл, который применяет макет пользовательской учетной записи к компонентам в папке:

@using BlazorSample.Components.Account.Shared
@layout AccountLayout

Папка Shared поддерживает компонент макета AccountLayout . Компонент используется HttpContext для определения того, является ли компонент отрисовкой на сервере. Identity Компоненты должны отображаться на сервере со статическим SSR, так как они задают Identitycookies. Если значение HttpContext равно null, компонент отображается в интерактивном режиме, а полностраничная перезагрузка выполняется путем вызова NavigationManager.Refresh с forceLoad заданным значением true. Это заставляет полный rerender страницы использовать статический SSR.

Components/Account/Shared/AccountLayout.razor:

@inherits LayoutComponentBase
@layout BlazorSample.Components.Layout.MainLayout
@inject NavigationManager NavigationManager

@if (HttpContext is null)
{
    <p>Loading...</p>
}
else
{
    @Body
}

@code {
    [CascadingParameter]
    private HttpContext? HttpContext { get; set; }

    protected override void OnParametersSet()
    {
        if (HttpContext is null)
        {
            NavigationManager.Refresh(forceReload: true);
        }
    }
}

Примечание.

В шаблоне Blazor проекта веб-приложения есть второй файл макета (ManageLayout.razor в Components/Account/Shared папке) для Identity компонентов в папке Components/Account/Pages/Manage . Папка Manage имеет собственный _Imports.razor файл для применения к ManageLayout компонентам в папке. В собственных приложениях использование вложенных _Imports.razor файлов — это полезный подход для применения пользовательских макетов к группам страниц.

В компоненте App любой запрос на компонент в Account папке применяет режим отрисовки, который применяет статический null SSR. Другие запросы компонентов получают глобальное приложение интерактивного режима отрисовки SSR (InteractiveServer).

Внимание

Применение режима отрисовки не всегда применяет статический null SSR. Это просто происходит, чтобы вести себя таким образом, используя подход, показанный в этом разделе.

null Режим отрисовки фактически совпадает с указанием режима отрисовки, что приводит к наследоваванию компонента родительского режима отрисовки. В этом случае App компонент отрисовывается с помощью статического SSR, поэтому null режим отрисовки App приводит к Routes наследованию статического SSR от компонента. Если для дочернего компонента, родительский элемент которого использует режим интерактивной отрисовки, то дочерний элемент наследует тот же интерактивный режим отрисовки.

Components/App.razor:

<Routes @rendermode="RenderModeForPage" />

...

@code {
    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? RenderModeForPage => 
        HttpContext.Request.Path.StartsWithSegments("/Account")
            ? null
            : {INTERACTIVE RENDER MODE};
}

В приведенном выше коде измените {INTERACTIVE RENDER MODE} заполнитель на соответствующее значение в зависимости от того, должен ли остальная часть приложения принимать глобальные InteractiveServerили InteractiveAutoInteractiveWebAssemblyотрисовки.

Компоненты, которые должны принимать статический SSR в Account папке, не требуются для задания макета, так как он применяется через _Imports.razor файл, и компоненты не задают режим отрисовки, так как они должны отрисовывать статический SSR. Для компонентов в папке Account для принудительного применения статического SSR не требуется ничего дополнительного.

Статические компоненты SSR, распределенные по всему приложению

В предыдущем подразделе приложение управляет режимом отрисовки компонентов, задав режим отрисовки глобально в компонентеApp. Кроме того, App компонент также может применять режимы отрисовки для каждого компонента для настройки режима отрисовки, что позволяет компонентам распространяться по приложению для принудительного внедрения статического SSR. В этом подразделе описывается подход.

Приложение имеет пользовательский макет, который можно применить к компонентам вокруг приложения. Обычно общий компонент для приложения помещается в папку Components/Layout . Компонент используется HttpContext для определения того, является ли компонент отрисовкой на сервере. Если значение HttpContext равно null, компонент отображается в интерактивном режиме, а полностраничная перезагрузка выполняется путем вызова NavigationManager.Refresh с forceLoad заданным значением true. Это активирует запрос на сервер для компонента.

Components/Layout/StaticSsrLayout.razor:

@inherits LayoutComponentBase
@layout MainLayout
@inject NavigationManager NavigationManager

@if (HttpContext is null)
{
    <p>Loading...</p>
}
else
{
    @Body
}

@code {
    [CascadingParameter]
    private HttpContext? HttpContext { get; set; }

    protected override void OnParametersSet()
    {
        if (HttpContext is null)
        {
            NavigationManager.Refresh(forceReload: true);
        }
    }
}

В компоненте App для задания режима отрисовки используется отражение. Любой режим отрисовки, назначенный файлу определения отдельного компонента, применяется к компоненту Routes .

Components/App.razor:

<Routes @rendermode="RenderModeForPage" />

...

@code {
    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? RenderModeForPage =>
        HttpContext.GetEndpoint()?.Metadata.GetMetadata<RenderModeAttribute>()?
            .Mode;
}

Каждый компонент, который должен принимать статический SSR, задает пользовательский макет и не задает режим отрисовки. Не указывая режим отрисовки, он приводит к null значению RenderModeAttribute.Mode компонента App , что приводит к тому, что режим отрисовки не назначен Routes экземпляру компонента и принудительному применению статического SSR.

Внимание

Применение режима отрисовки не всегда применяет статический null SSR. Это просто происходит, чтобы вести себя таким образом, используя подход, показанный в этом разделе.

null Режим отрисовки фактически совпадает с указанием режима отрисовки, что приводит к наследоваванию компонента родительского режима отрисовки. В этом случае App компонент отрисовывается с помощью статического SSR, поэтому null режим отрисовки App приводит к Routes наследованию статического SSR от компонента. Если для дочернего компонента, родительский элемент которого использует режим интерактивной отрисовки, то дочерний элемент наследует тот же интерактивный режим отрисовки.

Для применения статического SSR компоненты не должны выполнять никаких действий, чем применение пользовательского макета без настройки интерактивного режима отрисовки:

@layout BlazorSample.Components.Layout.StaticSsrLayout

Интерактивные компоненты вокруг приложения не применяют пользовательский статический макет SSR и задают только соответствующий интерактивный режим отрисовки, который при отражении в App компоненте применяется к Routes компоненту:

@rendermode {INTERACTIVE RENDER MODE}

В приведенном выше коде измените {INTERACTIVE RENDER MODE} заполнитель на соответствующее значение в зависимости от того, должен ли компонент использовать InteractiveServerили InteractiveWebAssemblyInteractiveAuto отрисовку.

Не удается разрешить клиентские службы во время предварительной подготовки

Если предварительное создание не отключено для компонента или для приложения, компонент в .Client проекте предварительно отображается на сервере. Так как сервер не имеет доступа к зарегистрированным клиентским Blazor службам, невозможно внедрить эти службы в компонент без получения ошибки, которую служба не может быть найдена во время предварительной отрисовки.

Например, рассмотрим следующий Home компонент проекта в .ClientBlazor веб-приложении с глобальным интерактивным веб-отображением WebAssembly или интерактивной автоматической отрисовкой. Компонент пытается внедрить IWebAssemblyHostEnvironment имя среды.

@page "/"
@inject IWebAssemblyHostEnvironment Environment

<PageTitle>Home</PageTitle>

<h1>Home</h1>

<p>
    Environment: @Environment.Environment
</p>

Ошибка времени компиляции не возникает, но во время предварительной подготовки возникает ошибка среды выполнения:

Не удается указать значение свойства "Среда" в типе Sample.Client.PagesBlazor..Home Зарегистрированная служба типа Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment отсутствует.

Эта ошибка возникает из-за того, что компонент должен компилировать и выполнять на сервере во время предварительной подготовки, но IWebAssemblyHostEnvironment не является зарегистрированной службой на сервере.

Если приложению не требуется значение во время предварительной подготовки, эта проблема может быть решена путем внедрения IServiceProvider для получения службы вместо самого типа службы:

@page "/"
@using Microsoft.AspNetCore.Components.WebAssembly.Hosting
@inject IServiceProvider Services

<PageTitle>Home</PageTitle>

<h1>Home</h1>

<p>
    <b>Environment:</b> @environmentName
</p>

@code {
    private string? environmentName;

    protected override void OnInitialized()
    {
        if (Services.GetService<IWebAssemblyHostEnvironment>() is { } env)
        {
            environmentName = env.Environment;
        }
    }
}

Однако предыдущий подход не полезен, если логика требует значения во время предварительной подготовки.

Вы также можете избежать проблемы, если отключить предварительную отрисовку для компонента, но это крайняя мера, которую необходимо принять во многих случаях, которые могут не соответствовать спецификациям компонента.

Существует три подхода, которые можно предпринять для решения этого сценария. Ниже перечислены наиболее рекомендуемые по крайней мере рекомендуемые значения.

  • Рекомендуется для служб общей платформы: для служб общей платформы, которые просто не зарегистрированы на стороне сервера в основном проекте, зарегистрируйте службы в основном проекте, что делает их доступными во время предварительной подготовки. Пример этого сценария см. в руководстве по HttpClient службам в вызове веб-API из приложения ASP.NET CoreBlazor.

  • Рекомендуется использовать службы за пределами общей платформы: создайте пользовательскую реализацию службы для службы на сервере. Обычно используйте службу в интерактивных компонентах .Client проекта. Демонстрация этого подхода см. в ASP.NET основных Blazor средах.

  • Создайте абстракцию службы и создайте реализации для службы в .Client проектах сервера и серверных проектов. Зарегистрируйте службы в каждом проекте. Внедрение пользовательской службы в компонент.

  • Вы можете добавить .Client ссылку на пакет проекта на стороне сервера и вернуться к использованию API на стороне сервера при предварительной подготовке на сервере.

Обнаружение компонентов из дополнительных сборок

Дополнительные сборки должны быть раскрыты в Blazor платформе для обнаружения routable Razor компонентов в ссылочных проектах. Дополнительные сведения см. в статье Маршрутизация ASP.NET Core Blazor и навигация.

Закрытие каналов при отсутствии оставшихся компонентов интерактивного сервера

Компоненты интерактивного сервера обрабатывают события веб-интерфейса с помощью подключения в режиме реального времени к браузеру, называемому каналом. Канал и связанное с ним состояние создаются при отрисовки корневого компонента интерактивного сервера. Канал закрывается, если на странице нет оставшихся компонентов интерактивного сервера, что освобождает ресурсы сервера.

Настраиваемые режимы отрисовки с короткими данными

Директива @rendermode принимает один параметр, который является статическим экземпляром типа IComponentRenderMode. Атрибут @rendermode директивы может принимать любой экземпляр режима отрисовки, статический или нет. Платформа Blazor предоставляет статический RenderMode класс с некоторыми предопределенными режимами отрисовки для удобства, но вы можете создать собственные.

Обычно компонент использует следующую @rendermode директиву для отключения предварительной подготовки:

@rendermode @(new InteractiveServerRenderMode(prerender: false))

Однако рассмотрим следующий пример, который создает короткий интерактивный режим отрисовки на стороне сервера без предварительной подготовки через файл приложения _Imports (Components/_Imports.razor):

public static IComponentRenderMode InteractiveServerWithoutPrerendering { get; } = 
    new InteractiveServerRenderMode(prerender: false);

Используйте сокращенный режим отрисовки в компонентах во всей папке Components :

@rendermode InteractiveServerWithoutPrerendering

Кроме того, один экземпляр компонента может определить пользовательский режим отрисовки через частное поле:

@rendermode interactiveServerWithoutPrerendering

...

@code {
    private static IComponentRenderMode interactiveServerWithoutPrerendering = 
        new InteractiveServerRenderMode(prerender: false);
}

На данный момент подход к режиму краткого отображения, вероятно, полезен только для уменьшения детализации указания флага prerender . Короткий подход может оказаться более полезным в будущем, если дополнительные флаги становятся доступными для интерактивной отрисовки, и вы хотите создать режимы отрисовки с различными сочетаниями флагов.

Внедрение службы с помощью файла импорта верхнего уровня (_Imports.razor)

Этот раздел применяется только к Blazor веб-приложения.

Файл импорта верхнего уровня в папку (Components/_Imports.razor) внедряет ссылки на все компоненты в Components иерархии папок, включая App компонент (App.razor). Компонент App всегда отображается статически, даже если предварительная отрисовка компонента страницы отключена. Поэтому внедрение служб через файл импорта верхнего уровня приводит к разрешению двух экземпляров службы в компонентах страниц.

Чтобы устранить этот сценарий, введите службу в новый файл импорта, помещенный в папку Pages (Components/Pages/_Imports.razor). В этом расположении служба разрешается только один раз в компонентах страниц.

Дополнительные ресурсы