Модели размещения Blazor ASP.NET CoreASP.NET Core Blazor hosting models

По Даниэль Roth)By Daniel Roth

Важно!

Blazor WebAssembly (предварительная версия)Blazor WebAssembly in preview

Blazor Server поддерживается только в ASP.NET Core 3.0 и последующих версиях.Blazor Server is supported in ASP.NET Core 3.0. Blazor WebAssembly предоставляется как предварительная версия для ASP.NET Core 3.1.Blazor WebAssembly is in preview for ASP.NET Core 3.1.

Blazor — это веб-платформа, предназначенная для запуска на стороне клиента в браузере в среде выполнения .NET на основе сборки(Blazor веб- сборки) или на стороне сервера в ASP.NET Core ( Blazor Server). is a web framework designed to run client-side in the browser on a WebAssembly-based .NET runtime (Blazor WebAssembly) or server-side in ASP.NET Core (Blazor Server). Независимо от модели размещения, модели приложения и компонента одинаковы.Regardless of the hosting model, the app and component models are the same.

Сведения о создании проекта для моделей размещения, описанных в этой статье, см. в разделе Get started with ASP.NET Core Blazor.To create a project for the hosting models described in this article, see Get started with ASP.NET Core Blazor.

Blazor WebAssembly WebAssembly

Основная модель размещения для Blazor работает на стороне клиента в браузере на веб-сборке.The principal hosting model for Blazor is running client-side in the browser on WebAssembly. Приложение Blazor, его зависимости и среда выполнения .NET скачиваются в браузере.The Blazor app, its dependencies, and the .NET runtime are downloaded to the browser. Приложение выполняется непосредственно в потоке пользовательского интерфейса браузера.The app is executed directly on the browser UI thread. Обновления пользовательского интерфейса и обработка событий выполняются в рамках одного процесса.UI updates and event handling occur within the same process. Ресурсы приложения развертываются как статические файлы на веб-сервере или в службе, способной обслуживать статические содержимое клиентам.The app's assets are deployed as static files to a web server or service capable of serving static content to clients.

[! Операцион. NO-LOC (Блазор)]. сборка: [! Операцион. Приложение NO-LOC (Блазор)] выполняется в потоке пользовательского интерфейса в браузере. WebAssembly: The Blazor app runs on a UI thread inside the browser.

Чтобы создать Blazor приложение с помощью клиентской модели размещения, используйте шаблон приложенияBlazor сборки (DotNet New блазорвасм).To create a Blazor app using the client-side hosting model, use the Blazor WebAssembly App template (dotnet new blazorwasm).

ВыбравBlazor шаблон приложения-сборки , вы можете настроить приложение для использования ASP.NET Core серверной части, установив флажок ASP.NET Core Hosted (DotNet New блазорвасм — Hosted).After selecting the Blazor WebAssembly App template, you have the option of configuring the app to use an ASP.NET Core backend by selecting the ASP.NET Core hosted check box (dotnet new blazorwasm --hosted). ASP.NET Core приложение обслуживает Blazor приложение клиентам.The ASP.NET Core app serves the Blazor app to clients. Blazor приложение веб-сборки может взаимодействовать с сервером по сети с помощью вызовов или SignalR.The Blazor WebAssembly app can interact with the server over the network using web API calls or SignalR.

Шаблоны включают скрипт блазор... js , который обрабатывает:The templates include the blazor.webassembly.js script that handles:

  • Загрузка среды выполнения .NET, приложения и зависимостей приложения.Downloading the .NET runtime, the app, and the app's dependencies.
  • Инициализация среды выполнения для запуска приложения.Initialization of the runtime to run the app.

Модель размещения Blazorных сборок предоставляет несколько преимуществ.The Blazor WebAssembly hosting model offers several benefits:

  • Зависимость на стороне сервера .NET отсутствует.There's no .NET server-side dependency. Приложение полностью работает после загрузки на клиент.The app is fully functioning after downloaded to the client.
  • Ресурсы и возможности клиента полностью используются.Client resources and capabilities are fully leveraged.
  • Работа разгружается с сервера на клиент.Work is offloaded from the server to the client.
  • Веб-сервер ASP.NET Core не требуется для размещения приложения.An ASP.NET Core web server isn't required to host the app. Возможны сценарии бессерверного развертывания (например, обслуживание приложения из CDN).Serverless deployment scenarios are possible (for example, serving the app from a CDN).

Существует недостаток для Blazor размещения сборки:There are downsides to Blazor WebAssembly hosting:

  • Приложение ограничено возможностями браузера.The app is restricted to the capabilities of the browser.
  • Требуется аппаратное и программное обеспечение, поддерживающее клиент (например, поддержка сборок).Capable client hardware and software (for example, WebAssembly support) is required.
  • Размер скачивания больше, и приложения загружаются дольше.Download size is larger, and apps take longer to load.
  • Поддержка среды выполнения .NET и инструментария менее зрела..NET runtime and tooling support is less mature. Например, существуют ограничения на поддержку и отладку .NET Standard .For example, limitations exist in .NET Standard support and debugging.

Сервер BlazorBlazor Server

При использовании модели размещения сервера Blazor приложение выполняется на сервере из приложения ASP.NET Core.With the Blazor Server hosting model, the app is executed on the server from within an ASP.NET Core app. Обновление элементов пользовательского интерфейса, обработка событий и вызовы JavaScript обрабатываются через подключение SignalR.UI updates, event handling, and JavaScript calls are handled over a SignalR connection.

Браузер взаимодействует с приложением (размещенным в приложении ASP.NET Core) на сервере через [! Операцион. НЕТ-LOC (SignalR)] подключение.

Чтобы создать Blazor приложение с помощью модели размещения сервера Blazor, используйте шаблон серверного приложения ASP.NET CoreBlazor (DotNet New блазорсервер).To create a Blazor app using the Blazor Server hosting model, use the ASP.NET Core Blazor Server App template (dotnet new blazorserver). Приложение ASP.NET Core размещает приложение Blazor Server и создает конечную точку SignalR, в которую подключаются клиенты.The ASP.NET Core app hosts the Blazor Server app and creates the SignalR endpoint where clients connect.

ASP.NET Core приложение ссылается на класс Startup приложения для добавления:The ASP.NET Core app references the app's Startup class to add:

  • Службы на стороне сервера.Server-side services.
  • Приложение в конвейер обработки запросов.The app to the request handling pipeline.

Скрипт блазор. Server. js† устанавливает клиентское соединение.The blazor.server.js script† establishes the client connection. Ответственность за сохранение и восстановление состояния приложения в случае необходимости (например, в случае потери сетевого подключения) несет приложение.It's the app's responsibility to persist and restore app state as required (for example, in the event of a lost network connection).

Модель размещения серверов Blazor предлагает несколько преимуществ.The Blazor Server hosting model offers several benefits:

  • Размер загружаемого файла значительно меньше, чем Blazor приложение сборки, и приложение загружается гораздо быстрее.Download size is significantly smaller than a Blazor WebAssembly app, and the app loads much faster.
  • Приложение обладает всеми преимуществами серверных возможностей, включая использование любых API-интерфейсов, совместимых с .NET Core.The app takes full advantage of server capabilities, including use of any .NET Core compatible APIs.
  • .NET Core на сервере используется для запуска приложения, поэтому существующие инструменты .NET, такие как отладка, работают должным образом..NET Core on the server is used to run the app, so existing .NET tooling, such as debugging, works as expected.
  • Поддерживаются тонкие клиенты.Thin clients are supported. Например, Blazor серверные приложения работают с браузерами, которые не поддерживают сборку и устройства с ограниченными ресурсами.For example, Blazor Server apps work with browsers that don't support WebAssembly and on resource-constrained devices.
  • База .NET (C# код) приложения, включая код компонента приложения, не обслуживаются для клиентов.The app's .NET/C# code base, including the app's component code, isn't served to clients.

Существуют недостатки Blazor размещения сервера:There are downsides to Blazor Server hosting:

  • Обычно существует большая задержка.Higher latency usually exists. Каждое взаимодействие с пользователем включает сетевой прыжок.Every user interaction involves a network hop.
  • Автономная поддержка отсутствует.There's no offline support. Если подключение клиента завершается сбоем, приложение перестает работать.If the client connection fails, the app stops working.
  • Масштабируемость — это сложная задача для приложений с большим количеством пользователей.Scalability is challenging for apps with many users. Сервер должен управлять несколькими клиентскими подключениями и обрабатывать состояние клиента.The server must manage multiple client connections and handle client state.
  • Для обслуживания приложения требуется сервер ASP.NET Core.An ASP.NET Core server is required to serve the app. Сценарии бессерверного развертывания невозможны (например, обслуживание приложения из CDN).Serverless deployment scenarios aren't possible (for example, serving the app from a CDN).

†сценарий блазор. Server. js обслуживается из внедренного ресурса в ASP.NET Core общей платформе.†The blazor.server.js script is served from an embedded resource in the ASP.NET Core shared framework.

Сравнение с ИНТЕРФЕЙСом, отображаемым серверомComparison to server-rendered UI

Одним из способов понимания Blazor серверных приложений является понимание того, как оно отличается от традиционных моделей для отрисовки пользовательского интерфейса в ASP.NET Core приложениях с помощью представлений Razor или Razor Pages.One way to understand Blazor Server apps is to understand how it differs from traditional models for rendering UI in ASP.NET Core apps using Razor views or Razor Pages. В обеих моделях используется язык Razor для описания содержимого HTML, но они значительно отличаются от отрисовки разметки.Both models use the Razor language to describe HTML content, but they significantly differ in how markup is rendered.

При отрисовке страницы Razor или представления каждая строка кода Razor выдает HTML в виде текста.When a Razor Page or view is rendered, every line of Razor code emits HTML in text form. После отрисовки сервер удаляет экземпляр страницы или представления, включая любое созданное состояние.After rendering, the server disposes of the page or view instance, including any state that was produced. Когда происходит другой запрос к странице, например при сбое проверки сервера и отображении сводки проверки:When another request for the page occurs, for instance when server validation fails and the validation summary is displayed:

  • Вся страница снова преобразуется в HTML-текст.The entire page is rerendered to HTML text again.
  • Страница отправляется клиенту.The page is sent to the client.

Blazor приложение состоит из многократно используемых элементов пользовательского интерфейса, называемых компонентами.A Blazor app is composed of reusable elements of UI called components. Компонент содержит C# код, разметку и другие компоненты.A component contains C# code, markup, and other components. При подготовке компонента к просмотру Blazor создает граф включенных компонентов, аналогичный HTML-или модель DOM XML (DOM).When a component is rendered, Blazor produces a graph of the included components similar to an HTML or XML Document Object Model (DOM). Эта диаграмма включает в себя состояние компонента, содержащееся в свойствах и полях.This graph includes component state held in properties and fields. Blazor оценивает граф компонентов для создания двоичного представления разметки. evaluates the component graph to produce a binary representation of the markup. Двоичный формат может быть следующим:The binary format can be:

  • Преобразуется в текст HTML (во время предварительной отрисовки).Turned into HTML text (during prerendering).
  • Используется для эффективного обновления разметки во время обычной отрисовки.Used to efficiently update the markup during regular rendering.

Обновление пользовательского интерфейса в Blazor активируется следующим образом:A UI update in Blazor is triggered by:

  • Взаимодействие с пользователем, например выбор кнопки.User interaction, such as selecting a button.
  • Триггеры приложений, например таймер.App triggers, such as a timer.

Граф перерисовывается, и вычисляется различие в пользовательском интерфейсе (разница).The graph is rerendered, and a UI diff (difference) is calculated. Это различие является наименьшим набором изменений DOM, необходимых для обновления пользовательского интерфейса на клиенте.This diff is the smallest set of DOM edits required to update the UI on the client. Diff отправляется клиенту в двоичном формате и применяется в браузере.The diff is sent to the client in a binary format and applied by the browser.

Компонент уничтожается после того, как пользователь выходит из него с клиента.A component is disposed after the user navigates away from it on the client. Несмотря на то, что пользователь взаимодействует с компонентом, состояние компонента (службы, ресурсы) должно храниться в памяти сервера.While a user is interacting with a component, the component's state (services, resources) must be held in the server's memory. Так как состояние множества компонентов может поддерживаться сервером одновременно, нехватка памяти является проблемой, которую необходимо решить.Because the state of many components might be maintained by the server concurrently, memory exhaustion is a concern that must be addressed. Инструкции по созданию приложения Blazor Server для обеспечения оптимального использования памяти сервера см. в разделе Безопасные ASP.NET Core Blazor серверные приложения.For guidance on how to author a Blazor Server app to ensure the best use of server memory, see Безопасные ASP.NET Core Blazor серверные приложения.

ЗащитCircuits

Серверное приложение Blazor построено на основе ASP.NET Core SignalR.A Blazor Server app is built on top of ASP.NET Core SignalR. Каждый клиент взаимодействует с сервером через одно или несколько SignalR соединений, называемых каналом.Each client communicates to the server over one or more SignalR connections called a circuit. Цепь — это Blazorабстракции для SignalR подключений, которые могут допускать временные перерывы в сети.A circuit is Blazor's abstraction over SignalR connections that can tolerate temporary network interruptions. Когда клиент Blazor видит, что SignalRное подключение отключено, оно пытается повторно подключиться к серверу с помощью нового соединения SignalR.When a Blazor client sees that the SignalR connection is disconnected, it attempts to reconnect to the server using a new SignalR connection.

Каждый экран браузера (вкладка браузера или IFRAME), подключенный к Blazor серверному приложению, использует SignalRное соединение.Each browser screen (browser tab or iframe) that is connected to a Blazor Server app uses a SignalR connection. Это еще одно важное различие по сравнению с обычными серверно-визуализированными приложениями.This is yet another important distinction compared to typical server-rendered apps. В приложении, готовом для просмотра, открытие одного и того же приложения на нескольких экранах браузера обычно не приводит к дополнительным требованиям к ресурсам на сервере.In a server-rendered app, opening the same app in multiple browser screens typically doesn't translate into additional resource demands on the server. В приложении Blazor Server каждый экран браузера требует отдельного канала и отдельных экземпляров состояния компонента для управления сервером.In a Blazor Server app, each browser screen requires a separate circuit and separate instances of component state to be managed by the server.

Blazor рассматривает закрытие вкладки браузера или переход по внешнему URL-адресу корректное завершение. considers closing a browser tab or navigating to an external URL a graceful termination. В случае корректного завершения работы канал и связанные ресурсы немедленно освобождаются.In the event of a graceful termination, the circuit and associated resources are immediately released. Клиент может также отключиться от некорректного, например, из-за прерывания работы сети.A client may also disconnect non-gracefully, for instance due to a network interruption. Blazor Server хранит отключенные цепи в течение настраиваемого интервала, чтобы разрешить клиенту повторное подключение. Server stores disconnected circuits for a configurable interval to allow the client to reconnect. Дополнительные сведения см. в разделе повторное Подключение к тому же серверу .For more information, see the Reconnection to the same server section.

Задержка пользовательского интерфейсаUI Latency

Задержка пользовательского интерфейса — это время, которое занимает от инициированного действия до момента обновления пользовательского интерфейса.UI latency is the time it takes from an initiated action to the time the UI is updated. Меньшее значение задержки пользовательского интерфейса является обязательным, чтобы приложение было легко реагировать на пользователя.Smaller values for UI latency are imperative for an app to feel responsive to a user. В приложении Blazor Server каждое действие отправляется на сервер, обрабатывается, и разница пользовательского интерфейса отсылается обратно.In a Blazor Server app, each action is sent to the server, processed, and a UI diff is sent back. Следовательно, задержка пользовательского интерфейса — это сумма задержки в сети и задержки сервера при обработке действия.Consequently, UI latency is the sum of network latency and the server latency in processing the action.

Для бизнес-приложения, которое ограничено частной корпоративной сетью, воздействие на восприятие пользователей задержки из-за задержки в сети обычно незаметно.For a line of business app that's limited to a private corporate network, the effect on user perceptions of latency due to network latency are usually imperceptible. Для приложения, развернутого через Интернет, задержка может стать заметным для пользователей, особенно в том случае, если пользователи широко распределены географически.For an app deployed over the Internet, latency may become noticeable to users, particularly if users are widely distributed geographically.

Использование памяти может также повлиять на задержку приложения.Memory usage can also contribute to app latency. Увеличение использования памяти приводит к частым сборкам мусора или выделению памяти на диск, что снижает производительность приложений и, следовательно, увеличивает задержку пользовательского интерфейса.Increased memory usage results in frequent garbage collection or paging memory to disk, both of which degrade app performance and consequently increase UI latency. Для получения дополнительной информации см. Безопасные ASP.NET Core Blazor серверные приложения.For more information, see Безопасные ASP.NET Core Blazor серверные приложения.

Blazor серверные приложения должны быть оптимизированы для минимизации задержки пользовательского интерфейса за счет уменьшения задержки сети и использования памяти. Server apps should be optimized to minimize UI latency by reducing network latency and memory usage. Способ измерения задержки в сети см. в разделе Размещение и развертывание серверного приложения Blazor с помощью ASP.NET Core.For an approach to measuring network latency, see Размещение и развертывание серверного приложения Blazor с помощью ASP.NET Core. Дополнительные сведения о SignalR и Blazorсм. в следующих статьях:For more information on SignalR and Blazor, see:

Соединение с серверомConnection to the server

для Blazor серверных приложений требуется активное подключение SignalR к серверу.Blazor Server apps require an active SignalR connection to the server. Если соединение потеряно, приложение попытается повторно подключиться к серверу.If the connection is lost, the app attempts to reconnect to the server. Пока состояние клиента по-прежнему находится в памяти, сеанс клиента возобновляется без потери состояния.As long as the client's state is still in memory, the client session resumes without losing state.

Повторное подключение к тому же серверуReconnection to the same server

Приложение Blazor Server предварительно отображается в ответ на первый клиентский запрос, который настраивает состояние пользовательского интерфейса на сервере.A Blazor Server app prerenders in response to the first client request, which sets up the UI state on the server. Когда клиент пытается создать SignalR подключение, клиент должен повторно подключиться к тому же серверу.When the client attempts to create a SignalR connection, the client must reconnect to the same server. Blazor серверных приложений, использующих более одного внутреннего сервера, должны реализовывать закрепленные сеансы для SignalRных соединений. Server apps that use more than one backend server should implement sticky sessions for SignalR connections.

Мы рекомендуем использовать для серверных приложений Blazor службу Azure SignalR.We recommend using the Azure SignalR Service for Blazor Server apps. Она позволяет вертикально масштабировать серверные приложения Blazor для одновременного использования большого числа подключений SignalR.The service allows for scaling up a Blazor Server app to a large number of concurrent SignalR connections. Прикрепленные сеансы включены для службы SignalR Azure, задав для параметра ServerStickyMode или значения конфигурации службы значение Required.Sticky sessions are enabled for the Azure SignalR Service by setting the service's ServerStickyMode option or configuration value to Required. Для получения дополнительной информации см. Размещение и развертывание серверного приложения Blazor с помощью ASP.NET Core.For more information, see Размещение и развертывание серверного приложения Blazor с помощью ASP.NET Core.

При использовании IIS работа с прикрепленными сеансами включает маршрутизацию запросов приложений.When using IIS, sticky sessions are enabled with Application Request Routing. Дополнительные сведения см. в разделе Балансировка нагрузки HTTP с использованием маршрутизации запросов приложений.For more information, see HTTP Load Balancing using Application Request Routing.

Отражение состояния соединения в пользовательском интерфейсеReflect the connection state in the UI

Когда клиент обнаруживает, что соединение потеряно, пользователь по умолчанию отображает пользовательский интерфейс, когда клиент пытается повторно подключиться.When the client detects that the connection has been lost, a default UI is displayed to the user while the client attempts to reconnect. Если происходит сбой повторного подключения, пользователь предоставляет возможность повторить попытку.If reconnection fails, the user is provided the option to retry.

Чтобы настроить пользовательский интерфейс, определите элемент с id components-reconnect-modal в <body> страницы Razor _Host. cshtml :To customize the UI, define an element with an id of components-reconnect-modal in the <body> of the _Host.cshtml Razor page:

<div id="components-reconnect-modal">
    ...
</div>

В следующей таблице описаны классы CSS, применяемые к элементу components-reconnect-modal.The following table describes the CSS classes applied to the components-reconnect-modal element.

Класс CSSCSS class Указывает,…Indicates…
components-reconnect-show Утерянное подключение.A lost connection. Клиент пытается повторно подключиться.The client is attempting to reconnect. Отображение модального окна.Show the modal.
components-reconnect-hide Активное подключение будет восстановлено на сервере.An active connection is re-established to the server. Скрыть модальное окно.Hide the modal.
components-reconnect-failed Сбой повторного подключения, возможно, из-за сбоя сети.Reconnection failed, probably due to a network failure. Чтобы повторить попытку подключения, вызовите window.Blazor.reconnect().To attempt reconnection, call window.Blazor.reconnect().
components-reconnect-rejected Повторное подключение отклонено.Reconnection rejected. Сервер был достигнут, но отклонил подключение, и состояние пользователя на сервере потеряно.The server was reached but refused the connection, and the user's state on the server is lost. Чтобы перезагрузить приложение, вызовите location.reload().To reload the app, call location.reload(). Это состояние соединения может появиться в следующих случаях:This connection state may result when:
  • Происходит сбой в цепи на стороне сервера.A crash in the server-side circuit occurs.
  • Клиент отключается достаточно долго, чтобы сервер отключил состояние пользователя.The client is disconnected long enough for the server to drop the user's state. Удаляются экземпляры компонентов, с которыми взаимодействует пользователь.Instances of the components that the user is interacting with are disposed.
  • Сервер перезагружается, или рабочий процесс приложения перезапускается.The server is restarted, or the app's worker process is recycled.

Повторное подключение с отслеживанием состояния после предварительной подготовки к просмотруStateful reconnection after prerendering

Серверные приложения Blazor настроены по умолчанию для выprerender пользовательский интерфейс на сервере, прежде чем будет установлено клиентское соединение с сервером.Blazor Server apps are set up by default to prerender the UI on the server before the client connection to the server is established. Это настраивается на странице Razor _Host. cshtml :This is set up in the _Host.cshtml Razor page:

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

    <script src="_framework/blazor.server.js"></script>
</body>
<body>
    <app>@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))</app>

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

RenderMode настраивает, является ли компонент:RenderMode configures whether the component:

  • Предварительно отображается на странице.Is prerendered into the page.
  • Отображается как статический HTML на странице или включает необходимые сведения для начальной загрузки Blazor приложения из агента пользователя.Is rendered as static HTML on the page or if it includes the necessary information to bootstrap a Blazor app from the user agent.
RenderMode ОписаниеDescription
ServerPrerendered Преобразует компонент в статический HTML и включает маркер для Blazor серверного приложения.Renders the component into static HTML and includes a marker for a Blazor Server app. При запуске агента пользователя этот маркер используется для начальной загрузки Blazor приложения.When the user-agent starts, this marker is used to bootstrap a Blazor app.
Server Отображает маркер для серверного приложения Blazor.Renders a marker for a Blazor Server app. Выходные данные компонента не включаются.Output from the component isn't included. При запуске агента пользователя этот маркер используется для начальной загрузки Blazor приложения.When the user-agent starts, this marker is used to bootstrap a Blazor app.
Static Преобразует компонент в статический HTML.Renders the component into static HTML.
RenderMode ОписаниеDescription
ServerPrerendered Преобразует компонент в статический HTML и включает маркер для Blazor серверного приложения.Renders the component into static HTML and includes a marker for a Blazor Server app. При запуске агента пользователя этот маркер используется для начальной загрузки Blazor приложения.When the user-agent starts, this marker is used to bootstrap a Blazor app. Параметры не поддерживаются.Parameters aren't supported.
Server Отображает маркер для серверного приложения Blazor.Renders a marker for a Blazor Server app. Выходные данные компонента не включаются.Output from the component isn't included. При запуске агента пользователя этот маркер используется для начальной загрузки Blazor приложения.When the user-agent starts, this marker is used to bootstrap a Blazor app. Параметры не поддерживаются.Parameters aren't supported.
Static Преобразует компонент в статический HTML.Renders the component into static HTML. Поддерживаются параметры.Parameters are supported.

Отрисовка компонентов сервера из статической HTML-страницы не поддерживается.Rendering server components from a static HTML page isn't supported.

Если RenderMode ServerPrerendered, компонент изначально отрисовывается статически как часть страницы.When RenderMode is ServerPrerendered, the component is initially rendered statically as part of the page. После того, как браузер установит соединение с сервером, компонент сноваготовится к просмотру, и теперь компонент является интерактивным.Once the browser establishes a connection back to the server, the component is rendered again, and the component is now interactive. Если имеется метод жизненно инициализированного метода жизненный цикл {Async} для инициализации компонента, метод выполняется дважды:If the OnInitialized{Async} lifecycle method for initializing the component is present, the method is executed twice:

  • Когда компонент предварительно отображается статически.When the component is prerendered statically.
  • После установки соединения с сервером.After the server connection has been established.

Это может привести к заметному изменению данных, отображаемых в пользовательском интерфейсе, когда компонент в итоге готовится к просмотру.This can result in a noticeable change in the data displayed in the UI when the component is finally rendered.

Чтобы избежать сценария двойной визуализации в приложении Blazor Server, выполните следующие действия.To avoid the double-rendering scenario in a Blazor Server app:

  • Передайте идентификатор, который можно использовать для кэширования состояния во время подготовки к просмотру, и для получения состояния после перезапуска приложения.Pass in an identifier that can be used to cache the state during prerendering and to retrieve the state after the app restarts.
  • Используйте идентификатор во время подготовки к просмотру для сохранения состояния компонента.Use the identifier during prerendering to save component state.
  • Используйте идентификатор после предварительной подготовки для получения кэшированного состояния.Use the identifier after prerendering to retrieve the cached state.

В следующем коде показано обновленное WeatherForecastService в серверном приложении Blazor на основе шаблонов, которое позволяет избежать двойной отрисовки:The following code demonstrates an updated WeatherForecastService in a template-based Blazor Server app that avoids the double rendering:

public class WeatherForecastService
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild",
        "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };
    
    public WeatherForecastService(IMemoryCache memoryCache)
    {
        MemoryCache = memoryCache;
    }
    
    public IMemoryCache MemoryCache { get; }

    public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
    {
        return MemoryCache.GetOrCreateAsync(startDate, async e =>
        {
            e.SetOptions(new MemoryCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = 
                    TimeSpan.FromSeconds(30)
            });

            var rng = new Random();

            await Task.Delay(TimeSpan.FromSeconds(10));

            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = startDate.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            }).ToArray();
        });
    }
}

Отображение интерактивных компонентов с отслеживанием состояния из страниц и представлений RazorRender stateful interactive components from Razor pages and views

Интерактивные компоненты с отслеживанием состояния могут быть добавлены на страницу Razor или в представление.Stateful interactive components can be added to a Razor page or view.

При визуализации страницы или представления:When the page or view renders:

  • Компонент предварительно отображается страницей или представлением.The component is prerendered with the page or view.
  • Исходное состояние компонента, используемое для предварительной визуализации, потеряно.The initial component state used for prerendering is lost.
  • Новое состояние компонента создается при установке подключения SignalR.New component state is created when the SignalR connection is established.

Следующая страница Razor визуализирует компонент Counter:The following Razor page renders a Counter component:

<h1>My Razor Page</h1>

<component type="typeof(Counter)" render-mode="ServerPrerendered" 
    param-InitialValue="InitialValue" />

@code {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}
<h1>My Razor Page</h1>

@(await Html.RenderComponentAsync<Counter>(RenderMode.ServerPrerendered))

@code {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

Прорисовка неинтерактивных компонентов на страницах и представлениях RazorRender noninteractive components from Razor pages and views

На следующей странице Razor компонент Counter статически подготавливается к просмотру с начальным значением, указанным с помощью формы:In the following Razor page, the Counter component is statically rendered with an initial value that's specified using a form:

<h1>My Razor Page</h1>

<form>
    <input type="number" asp-for="InitialValue" />
    <button type="submit">Set initial value</button>
</form>

<component type="typeof(Counter)" render-mode="Static" 
    param-InitialValue="InitialValue" />

@code {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}
<h1>My Razor Page</h1>

<form>
    <input type="number" asp-for="InitialValue" />
    <button type="submit">Set initial value</button>
</form>

@(await Html.RenderComponentAsync<Counter>(RenderMode.Static, 
    new { InitialValue = InitialValue }))

@code {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

Поскольку MyComponent является статически отображаемым, компонент не может быть интерактивным.Since MyComponent is statically rendered, the component can't be interactive.

Обнаруживать время подготовки приложения к просмотруDetect when the app is prerendering

При предварительном отображении серверного приложения Блазор некоторые действия, такие как вызов JavaScript, не возможны, так как соединение с браузером не установлено.While a Blazor Server app is prerendering, certain actions, such as calling into JavaScript, aren't possible because a connection with the browser hasn't been established. При предварительной отрисовке компонентов может потребоваться прорисовка по-разному.Components may need to render differently when prerendered.

Чтобы отложить вызовы взаимодействия JavaScript до тех пор, пока не будет установлено подключение к браузеру, можно использовать событие жизненного цикла компонента онафтеррендерасинк.To delay JavaScript interop calls until after the connection with the browser is established, you can use the OnAfterRenderAsync component lifecycle event. Это событие вызывается только после того, как приложение будет полностью визуализировано и установлено клиентское соединение.This event is only called after the app is fully rendered and the client connection is established.

@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<div @ref="divElement">Text during render</div>

@code {
    private ElementReference divElement;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSRuntime.InvokeVoidAsync(
                "setElementText", divElement, "Text after render");
        }
    }
}

В предыдущем примере кода укажите setElementText функцию JavaScript в элементе <head> wwwroot/index.HTML (блазор Assembly) или pages/_Host. cshtml (блазор Server).For the preceding example code, provide a setElementText JavaScript function inside the <head> element of wwwroot/index.html (Blazor WebAssembly) or Pages/_Host.cshtml (Blazor Server). Функция вызывается с IJSRuntime.InvokeVoidAsync и не возвращает значение:The function is called with IJSRuntime.InvokeVoidAsync and doesn't return a value:

<script>
  window.setElementText = (element, text) => element.innerText = text;
</script>

Предупреждение

В предыдущем примере модель DOM (модель DOM) изменяется непосредственно только в демонстрационных целях.The preceding example modifies the Document Object Model (DOM) directly for demonstration purposes only. Непосредственное изменение модели DOM с помощью JavaScript не рекомендуется в большинстве сценариев, поскольку JavaScript может мешать отслеживанию изменений Блазор.Directly modifying the DOM with JavaScript isn't recommended in most scenarios because JavaScript can interfere with Blazor's change tracking.

В следующем компоненте показано, как использовать взаимодействие JavaScript как часть логики инициализации компонента способом, совместимым с предварительной отрисовкой.The following component demonstrates how to use JavaScript interop as part of a component's initialization logic in a way that's compatible with prerendering. Компонент показывает, что можно активировать обновление отрисовки из OnAfterRenderAsync.The component shows that it's possible to trigger a rendering update from inside OnAfterRenderAsync. В этом сценарии разработчику следует избегать создания бесконечного цикла.The developer must avoid creating an infinite loop in this scenario.

При вызове JSRuntime.InvokeAsync ElementRef используется только в OnAfterRenderAsync, а не в каком-либо предыдущем методе жизненного цикла, так как нет элемента JavaScript до тех пор, пока не будет визуализирован компонент.Where JSRuntime.InvokeAsync is called, ElementRef is only used in OnAfterRenderAsync and not in any earlier lifecycle method because there's no JavaScript element until after the component is rendered.

Статехасчанжед вызывается для реотрисовки компонента с новым состоянием, полученным из вызова взаимодействия JavaScript.StateHasChanged is called to rerender the component with the new state obtained from the JavaScript interop call. Код не создает бесконечный цикл, так как StateHasChanged вызывается только при null``infoFromJs.The code doesn't create an infinite loop because StateHasChanged is only called when infoFromJs is null.

@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<p>
    Get value via JS interop call:
    <strong id="val-get-by-interop">@(infoFromJs ?? "No value yet")</strong>
</p>

Set value via JS interop call:
<div id="val-set-by-interop" @ref="divElement"></div>

@code {
    private string infoFromJs;
    private ElementReference divElement;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && infoFromJs == null)
        {
            infoFromJs = await JSRuntime.InvokeAsync<string>(
                "setElementText", divElement, "Hello from interop call!");

            StateHasChanged();
        }
    }
}

В предыдущем примере кода укажите setElementText функцию JavaScript в элементе <head> wwwroot/index.HTML (блазор Assembly) или pages/_Host. cshtml (блазор Server).For the preceding example code, provide a setElementText JavaScript function inside the <head> element of wwwroot/index.html (Blazor WebAssembly) or Pages/_Host.cshtml (Blazor Server). Функция вызывается с IJSRuntime.InvokeAsync и возвращает значение:The function is called with IJSRuntime.InvokeAsync and returns a value:

<script>
  window.setElementText = (element, text) => {
    element.innerText = text;
    return text;
  };
</script>

Предупреждение

В предыдущем примере модель DOM (модель DOM) изменяется непосредственно только в демонстрационных целях.The preceding example modifies the Document Object Model (DOM) directly for demonstration purposes only. Непосредственное изменение модели DOM с помощью JavaScript не рекомендуется в большинстве сценариев, поскольку JavaScript может мешать отслеживанию изменений Блазор.Directly modifying the DOM with JavaScript isn't recommended in most scenarios because JavaScript can interfere with Blazor's change tracking.

Настройка клиента SignalR для приложений Blazor ServerConfigure the SignalR client for Blazor Server apps

Иногда необходимо настроить клиент SignalR, используемый приложениями Blazor Server.Sometimes, you need to configure the SignalR client used by Blazor Server apps. Например, может потребоваться настроить ведение журнала на SignalRном клиенте для диагностики проблемы с подключением.For example, you might want to configure logging on the SignalR client to diagnose a connection issue.

Настройка клиента SignalR в файле pages/_Host. cshtml :To configure the SignalR client in the Pages/_Host.cshtml file:

  • Добавьте атрибут autostart="false" в тег <script> для скрипта блазор. Server. js .Add an autostart="false" attribute to the <script> tag for the blazor.server.js script.
  • Вызовите Blazor.start и передайте объект конфигурации, указывающий построитель SignalR.Call Blazor.start and pass in a configuration object that specifies the SignalR builder.
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      builder.configureLogging("information"); // LogLevel.Information
    }
  });
</script>

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