Поделиться через


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

Примечание.

Это не последняя версия этой статьи. В текущем выпуске смотрите версию .NET 9 этой статьи.

Внимание

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

В текущем выпуске см . версию .NET 9 этой статьи.

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

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

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

Каждый компонент в Blazor Web App использует режим отрисовки для определения модели размещения, где она отрисовывается, и является ли она интерактивной. Интерактивность позволяет пользователям взаимодействовать с визуализированными компонентами. В это входят ответы приложения на события объектной модели документа (DOM) и изменения состояния, которые привязаны к членам C# посредством обработчиков событий и привязки Blazor.

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

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

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

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

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

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

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

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

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

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

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

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

Расширения для построителя конвенций конечных точек:

Примечание.

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

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

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

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

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

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

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

Blazor использует хостинг-модель Blazor WebAssembly для скачивания и выполнения компонентов, использующих интерактивный режим рендеринга WebAssembly. Для настройки хостинга Blazor WebAssembly для этих компонентов требуется отдельный проект для клиента. Клиентский проект содержит код запуска узла Blazor WebAssembly и настраивает среду выполнения .NET для запуска в браузере. Шаблон Blazor Web App добавляет этот клиентский проект для вас при выборе параметра для включения интерактивности 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 Web App, режим отрисовки, назначенный всему приложению, обычно указывается в том месте, где компонент Routes используется в компоненте App (Components/App.razor):

<Routes @rendermode="InteractiveServer" />

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

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

<HeadOutlet @rendermode="InteractiveServer" />

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

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

Чтобы включить глобальное взаимодействие при создании Blazor Web App

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

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

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

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

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

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

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

@rendermode pageRenderMode

...

@code {
    private static IComponentRenderMode pageRenderMode = InteractiveServer;
}

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

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

<Routes @rendermode="PageRenderMode" />

...

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

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

Обнаружение расположения отрисовки, интерактивности и назначенного режима отрисовки во время выполнения

ComponentBase.RendererInfo Свойства ComponentBase.AssignedRenderMode позволяют приложению обнаруживать сведения о расположении, интерактивности и назначенном режиме отрисовки компонента:

  • RendererInfo.Name возвращает расположение, в котором выполняется компонент:
    • Static: на сервере (SSR) и не может взаимодействовать.
    • Server: на сервере (SSR) и может стать интерактивным после предварительного рендеринга.
    • WebAssembly: на клиенте (CSR) и способно к взаимодействию после предварительной отрисовки.
    • WebView: На родном устройстве и способен к взаимодействию после пререндера.
  • RendererInfo.IsInteractive указывает, поддерживает ли компонент интерактивность во время отрисовки. Значение — true, когда происходит интерактивная отрисовка, или false при предварительном рендеринге или для статического SSR (RendererInfo.Name из Static).
  • AssignedRenderMode предоставляет назначенный компоненту режим отрисовки:
    • InteractiveServerRenderMode для интерактивного сервера.
    • InteractiveAutoRenderMode для интерактивного авто.
    • InteractiveWebAssemblyRenderMode для интерактивного WebAssembly.
    • null, если режим отрисовки не назначен.

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

Отображение содержимого до тех пор, пока компонент не будет интерактивным:

@if (!RendererInfo.IsInteractive)
{
    <p>Connecting to the assistant...</p>
}
else
{
    ...
}

Отключите кнопку, пока компонент не будет интерактивным:

<button @onclick="Send" disabled="@(!RendererInfo.IsInteractive)">
    Send
</button>

Отключите форму во время предварительного рендеринга и включите форму при интерактивном состоянии компонента.

<EditForm Model="Movie" ...>
    <fieldset disabled="@disabled">

        ...

        <button type="submit" >Save</button>
    </fieldset>
</EditForm>

@code {
    private bool disabled = true;

    [SupplyParameterFromForm]
    private Movie? Movie { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Movie ??= await ...;

        if (RendererInfo.IsInteractive)
        {
            disabled = false;
        }
    }
}

Отрисовка HTML-разметки для поддержки выполнения обычного HTML-действия, если компонент статически отрисован.

@if (AssignedRenderMode is null)
{
    // The render mode is Static Server
    <form action="/movies">
        <input type="text" name="titleFilter" />
        <input type="submit" value="Search" />
    </form>
}
else
{
    // The render mode is Interactive Server, WebAssembly, or Auto
    <input @bind="titleFilter" />
    <button @onclick="FilterMovies">Search</button>
}

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

  • Если значение AssignedRenderMode равно null, компонент принимает статический SSR null. Blazor Обработка событий не работает в браузере со статическим SSR, поэтому компонент отправляет форму (ЗАПРОС GET) со строкой запроса, заданной titleFilter для значения пользователя <input> . Компонент Movie (/movie) может считывать строку запроса и обрабатывать значение titleFilter для отрисовки компонента с отфильтрованными результатами.
  • В противном случае режим отрисовки является любым из InteractiveServer, InteractiveWebAssemblyили InteractiveAuto. Компонент может использовать делегат обработчика событий FilterMovies и значение, привязанное к элементу <input>, titleFilter, для интерактивной фильтрации фильмов через фоновое подключение SignalR.

Blazor Примеры документации для Blazor Web Apps

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

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

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

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

Внутренняя навигация для интерактивной маршрутизации не включает запрос нового содержимого страницы с сервера. Таким образом, предварительная отрисовка не выполняется для внутренних запросов страниц, включая расширенную навигацию. Дополнительные сведения см. в разделе "Статическая и интерактивная маршрутизация", "Интерактивная маршрутизация" и "Предварительная подготовка" и "Улучшенная навигация" и "Обработка форм".

Отключение предварительной подготовки с помощью следующих методов действует только для режимов отрисовки верхнего уровня. Если родительский компонент задает режим рендеринга, параметры предварительного рендеринга дочерних элементов игнорируются. Это поведение рассматривается на предмет возможных изменений в связи с выпуском .NET 10 в ноябре 2025 года.

Чтобы отключить пререндеринг для экземпляра компонента, передайте флаг 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 Web App, режим отрисовки, примененный ко всему приложению, указывается там, где компонент 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 Web Appпоместите компонент в папку проекта 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. Взаимодействие с пользователем обрабатывается через подключение в режиме реального времени с браузером. Подключение цепи устанавливается при отрисовке компонента 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!";
    }
}

Если используете предыдущий компонент, поместите его в папку 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 Web Appв папку клиентского проекта Pages . Клиентский проект — это проект решения с именем, который заканчивается .Client. При запуске приложения введите /render-mode-3 в адресную строку браузера.

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

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

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

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

В следующем примере компонент является интерактивным во время процесса. Кнопка вызывает 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 Web Appв папку клиентского проекта Pages . Клиентский проект — это проект решения с именем, который заканчивается .Client. Когда приложение запущено, перейдите по адресу /render-mode-4 в адресной строке браузера.

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

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

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

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

В следующих примерах используется неизменяемый, нестраничный SharedMessage компонент. Независимый от режима отрисовки компонент не применяет режим отрисовки с директивой . Если вы тестируете эти сценарии с помощью Blazor Web App, поместите указанный компонент в папку приложения 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) становится интерактивным после того, как канал BlazorSignalR установлен.
  • Второй SharedMessage компонент с отрисовкой на стороне клиента (CSR) становится интерактивным после того, как пакет приложений загружен, и среда выполнения .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 Web App с компонентом 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), выполняемой исключительно на сервере, в то время как остальная часть приложения использует интерактивный режим отрисовки.

Этот подход полезен только в случае, если в приложении есть определенные страницы, которые не могут работать с интерактивным рендерингом на сервере или с использованием WebAssembly. Например, используйте этот подход для страниц, которые зависят от чтения и записи HTTP файлов cookie и могут работать только в цикле запроса-ответа вместо интерактивного рендеринга. Для страниц, работающих с интерактивной отрисовкой, не рекомендуется заставлять их использовать статический SSR, так как это менее эффективно и менее отзывчиво для конечного пользователя.

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

@attribute [ExcludeFromInteractiveRouting]

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

Метод RazorComponentsEndpointHttpContextExtensions.AcceptsInteractiveRouting расширения позволяет компоненту определить, применяется ли [ExcludeFromInteractiveRouting] атрибут к текущей странице.

В компоненте App используйте шаблон в следующем примере:

  • Страницы, которые не помечены атрибутом [ExcludeFromInteractiveRouting], по умолчанию переключаются в режим отрисовки InteractiveServer с глобальной интерактивностью. Вы можете заменить InteractiveServerInteractiveWebAssemblyInteractiveAuto или указать другой глобальный режим отрисовки по умолчанию.
  • Страницы, аннотированные атрибутом [ExcludeFromInteractiveRouting], принимают статический SSR (PageRenderMode назначается null).
<!DOCTYPE html>
<html>
<head>
    ...
    <HeadOutlet @rendermode="@PageRenderMode" />
</head>
<body>
    <Routes @rendermode="@PageRenderMode" />
    ...
</body>
</html>

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

    private IComponentRenderMode? PageRenderMode
        => HttpContext.AcceptsInteractiveRouting() ? InteractiveServer : null;
}

Альтернативой использованию метода расширения RazorComponentsEndpointHttpContextExtensions.AcceptsInteractiveRouting является чтение метаданных конечной точки вручную, используя HttpContext.GetEndpoint()?.Metadata.

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

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

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

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

Для примера подхода в этом разделе см. пример приложения BlazorWebAppAreaOfStaticSsrComponents. Метод, описанный в этом разделе, наиболее подходит для 8.0 Blazor Web App, но пример реализован в версии 9.0 с использованием функций Blazor, которые упрощают демонстрацию работы этого подхода.

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

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

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

Components/Account/_Imports.razor:

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

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

Components/Account/Shared/AccountLayout.razor:

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

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

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

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

Примечание.

В шаблоне проекта Blazor Web App для сценариев проверки подлинности есть второй файл макета (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 приводит к тому, что компонент Routes наследует статический SSR от компонента App. Если для дочернего компонента, родительский элемент которого использует режим интерактивной отрисовки, задан режим отрисовки null, дочерний компонент наследует тот же интерактивный режим отрисовки.

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, InteractiveWebAssemblyили InteractiveAuto отрисовки.

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

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

Для примера подхода в этом разделе см. пример приложения BlazorWebAppSpreadOutStaticSsrComponents. Метод, описанный в этом разделе, наиболее подходит для 8.0 Blazor Web App, но пример реализован в версии 9.0 с использованием функций Blazor, которые упрощают демонстрацию работы этого подхода.

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

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

Components/Layout/StaticSsrLayout.razor:

@inherits LayoutComponentBase
@layout MainLayout
@inject NavigationManager Navigation

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

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

    protected override void OnParametersSet()
    {
        if (HttpContext is null)
        {
            Navigation.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 компонент Routes наследует статический SSR от компонента App. Если для дочернего компонента задан нулевой режим рендеринга, а родительский элемент использует интерактивный режим рендеринга, то дочерний компонент наследует тот же интерактивный режим.

Для обеспечения статического SSR от компонентов не требуется ничего, кроме применения пользовательского макета без установки интерактивного режима отрисовки.

@layout BlazorSample.Components.Layout.StaticSsrLayout

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

@rendermode {INTERACTIVE RENDER MODE}

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

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

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

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

@page "/"
@inject IWebAssemblyHostEnvironment Environment

<PageTitle>Home</PageTitle>

<h1>Home</h1>

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

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

Не удается указать значение свойства "Среда" в типе BlazorSample.Client.Pages..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 Core Blazor» как пример этого сценария.

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

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

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

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

Дополнительные сборки должны быть объявлены в Blazor платформе для обнаружения маршрутизируемых 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 Web Apps.

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

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

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