Взаимодействие ASP.NET Core Blazor с JavaScript (JS-взаимодействие)

Примечание.

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

Внимание

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

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

Приложение Blazor может вызывать функции JavaScript (JS) из методов .NET и методы .NET из функций JS. Такой подход называется взаимодействием с JavaScript (JS-взаимодействием).

Дополнительные сведения о JS-взаимодействии можно найти в следующих статьях:

Примечание.

API взаимодействия JavaScript [JSImport]/[JSExport] доступен для клиентских компонентов в ASP.NET Core в .NET 7 или более поздней версии.

Дополнительные сведения см. в разделе "Импорт иJS экспорт JavaScriptJS" с ASP.NET CoreBlazor.

Сжатие для интерактивных компонентов сервера с ненадежными данными

С помощью сжатия, который включен по умолчанию, избегайте создания безопасных (прошедших проверку подлинности или авторизованных) интерактивных компонентов на стороне сервера, отрисовывающих данные из ненадежных источников. Ненадежные источники включают параметры маршрута, строки запроса, данные из JS взаимодействия и любой другой источник данных, которые сторонний пользователь может контролировать (базы данных, внешние службы). Дополнительные сведения см. в руководстве ASP.NET Основных BlazorSignalR руководствах по устранению угроз и устранении угроз для ASP.NET интерактивной отрисовки на стороне сервера ASP.NET CoreBlazor.

Абстракции взаимодействия JavaScript и пакет функций

Пакет () (Microsoft.JSInteropnpmjs.comпакет NuGet) предоставляет абстракции и функции взаимодействия между кодом .NET и JavaScript ().JS@microsoft/dotnet-js-interop Справочный dotnet/aspnetcore источник доступен в репозитории GitHub (/src/JSInterop папка). Дополнительные сведения см. в файле репозитория README.md GitHub.

Примечание.

По ссылкам в документации на справочные материалы по .NET обычно загружается ветвь репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список Switch branches or tags (Переключение ветвей или тегов). Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Дополнительные ресурсы для написания JS скриптов взаимодействия в TypeScript:

Взаимодействие с DOM

Изменить DOM с помощью JavaScript (JS) можно только в том случае, если объект не взаимодействует Blazor. Blazor поддерживает представления модели DOM и взаимодействует с объектами DOM напрямую. Если элемент, отображаемый Blazor, изменяется извне с помощью JS напрямую или путем взаимодействия с JS, модель DOM может больше не соответствовать внутреннему представлению Blazor, что может привести к неопределенному поведению. Неопределенное поведение может просто мешать представлению элементов или их функций, а может и представлять угрозу безопасности для приложения или сервера.

Это руководство применяется не только к вашему коду взаимодействия JS, но и к любым библиотекам JS, используемым приложением, включая все, что предоставляется сторонней платформой, например Bootstrap JS и jQuery.

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

Дополнительные сведения см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.

Асинхронные вызовы JavaScript

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

Дополнительные сведения см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.

Сериализация объектов

Blazor использует System.Text.Json для сериализации в соответствии с приведенными ниже требованиями и поведениями по умолчанию.

  • Типы должны иметь конструктор по умолчанию, методы доступа get/set должны быть общедоступными, а поля никогда не сериализуются.
  • Глобальная сериализация по умолчанию не настраивается во избежание повреждения существующих библиотек компонентов, негативного влияния на производительность и безопасность и снижения уровня надежности.
  • После сериализации имен членов .NET имена ключей JSON отображаются в нижнем регистре.
  • JSON десериализуется как экземпляры C# JsonElement, что допускает использование смешанного регистра. Внутреннее приведение для назначения свойствам модели C# работает как ожидалось, несмотря на различия между именами ключей JSON и именами свойств C#.
  • Сложные типы платформ, например KeyValuePair, могут быть обрезаны IL Trimmer при публикации и не присутствуют для JS взаимодействия. По умолчанию рекомендуется создавать настраиваемые типы для типов, которые триммер il Trimmer обрезает по умолчанию.

Для пользовательской сериализации доступен API JsonConverter. Свойства могут быть помечены атрибутом [JsonConverter] для переопределения сериализации по умолчанию для существующего типа данных.

Дополнительные сведения см. в ресурсах в документации по .NET:

Blazor поддерживает оптимизированное взаимодействие с массивом байтов JS, которое позволяет избежать кодирования и декодирования массивов байтов в Base64. Приложение может применять пользовательскую сериализацию и передавать результирующие байты. Дополнительные сведения см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.

При быстрой сериализации большого объема объектов .NET либо в случае необходимости сериализации больших объектов .NET или значительного количества объектов .NET Blazor поддерживает демаршалированное взаимодействие с JS. Дополнительные сведения см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.

Задачи очистки DOM во время удаления компонентов

Не выполняйте JS код взаимодействия для задач очистки DOM во время удаления компонентов. Вместо этого используйте MutationObserver шаблон в JavaScript (JS) на клиенте по следующим причинам:

  • Компонент, возможно, был удален из DOM по времени выполнения кода очистки Dispose{Async}.
  • Во время отрисовки Blazor на стороне сервера средство отрисовки может быть удалено платформой по времени выполнения кода очистки Dispose{Async}.

Шаблон MutationObserver позволяет запускать функцию при удалении элемента из DOM.

В следующем примере DOMCleanup компонент:

  • Содержит объект <div> с числом idcleanupDiv. Элемент <div> удаляется из DOM вместе с остальной разметкой компонента DOM при удалении компонента из DOM.
  • DOMCleanupJS Загружает класс из DOMCleanup.razor.js файла и вызывает ее createObserver функцию для настройки обратного MutationObserver вызова. Эти задачи выполняются в методе жизненного OnAfterRenderAsync цикла.

DOMCleanup.razor:

@page "/dom-cleanup"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>DOM Cleanup Example</h1>

<div id="cleanupDiv"></div>

@code {
    private IJSObjectReference? module;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./Components/Pages/DOMCleanup.razor.js");

            await module.InvokeVoidAsync("DOMCleanup.createObserver");
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
}

В следующем примере MutationObserver обратный вызов выполняется при каждом изменении DOM. Выполните код очистки, когда if инструкция подтверждает, что целевой элемент (cleanupDiv) был удален (if (targetRemoved) { ... }). Важно отключить и удалить MutationObserver память после выполнения кода очистки.

DOMCleanup.razor.js помещается параллельно с предыдущим DOMCleanup компонентом:

export class DOMCleanup {
  static observer;

  static createObserver() {
    const target = document.querySelector('#cleanupDiv');

    this.observer = new MutationObserver(function (mutations) {
      const targetRemoved = mutations.some(function (mutation) {
        const nodes = Array.from(mutation.removedNodes);
        return nodes.indexOf(target) !== -1;
      });

      if (targetRemoved) {
        // Cleanup resources here
        // ...

        // Disconnect and delete MutationObserver
        this.observer && this.observer.disconnect();
        delete this.observer;
      }
    });

    this.observer.observe(target.parentNode, { childList: true });
  }
}

window.DOMCleanup = DOMCleanup;

Вызовы взаимодействия JavaScript без канала

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

Вызовы взаимодействия JavaScriptJS () не могут быть выданы после SignalR отключения канала. Без канала во время удаления компонентов или в любое другое время, когда канал не существует, следующий метод вызывает сбой и записывает сообщение о том, что канал отключен как:JSDisconnectedException

Чтобы избежать ведения журнала JSDisconnectedException или регистрации пользовательских сведений, перехватите исключение в инструкции try-catch .

В следующем примере удаления компонентов:

  • Компонент реализует IAsyncDisposable.
  • Аргумент objInstance имеет тип IJSObjectReference.
  • JSDisconnectedException перехватываются и не регистрируются.
  • Кроме того, вы можете записывать пользовательские сведения в инструкцию catch на любом выбранном уровне журнала. В следующем примере не регистрируется пользовательская информация, так как предполагается, что разработчик не заботится о том, когда или где каналы отключены во время удаления компонентов.
async ValueTask IAsyncDisposable.DisposeAsync()
{
    try
    {
        if (objInstance is not null)
        {
            await objInstance.DisposeAsync();
        }
    }
    catch (JSDisconnectedException)
    {
    }
}

Если вы должны очистить собственные JS объекты или выполнить другой JS код на клиенте после потери канала, используйте MutationObserver шаблон в JS клиенте. Шаблон MutationObserver позволяет запускать функцию при удалении элемента из DOM.

Дополнительные сведения см. в следующих статьях:

Кэшированные файлы JavaScript

Файлы JavaScript (JS) и другие статические ресурсы обычно не кэшируются на клиентах во время разработки в среде Development. Во время разработки запросы статических ресурсов содержат заголовок Cache-Control со значением no-cache или max-age со значением, равным нулю (0).

На этапе производства в среде Production файлы JS обычно кэшируются клиентами.

Чтобы отключить кэширование на стороне клиента в браузерах, разработчики, как правило, используют один из следующих подходов:

Дополнительные сведения см. в разделе:

Ограничения размера для вызовов взаимодействия с JavaScript

Этот раздел относится только к интерактивным компонентам в серверных приложениях. Для клиентских компонентов платформа не накладывает ограничение на размер входных и выходных данных JavaScript (JS).

Для интерактивных компонентов в приложениях на стороне сервера вызовы взаимодействия, передавающие данные от клиента на сервер, JS ограничены максимальным размером входящих SignalR сообщений, разрешенным для методов концентратора (HubOptions.MaximumReceiveMessageSizeпо умолчанию: 32 КБ). Если размер сообщений SignalR (из JS в .NET) превышает MaximumReceiveMessageSize, возникает ошибка. Платформа не накладывает ограничение на размер сообщений SignalR от концентратора клиенту. Дополнительные сведения об ограничении размера, сообщениях об ошибках и рекомендациях по работе с ограничениями размера сообщений см . в ASP.NET основных BlazorSignalR руководствах.

Определение места выполнения приложения

Если это важно для приложения, чтобы узнать, где выполняется код для JS вызовов взаимодействия, используйте для OperatingSystem.IsBrowser определения, выполняется ли компонент в контексте браузера в WebAssembly.