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


HybridWebView

Просмотрите пример. Обзор примера

Пользовательский интерфейс многоплатформенного приложения .NET (.NET MAUI) HybridWebView позволяет размещать произвольное содержимое HTML/JS/CSS в веб-представлении и обеспечивает обмен данными между кодом в веб-представлении (JavaScript) и кодом, на котором размещено веб-представление (C#/.NET). Например, если у вас есть существующее приложение React JS, его можно разместить в кроссплатформенной машинном приложении .NET MAUI и создать серверную часть приложения с помощью C# и .NET.

HybridWebView определяет следующие свойства:

  • DefaultFile, типа string?, который указывает файл внутри HybridRoot, который должен служить файлом по умолчанию. Значение по умолчанию — index.html.
  • HybridRoot, типа string?, который представляет собой путь в необработанных ресурсах приложения, содержащий содержимое веб-приложения. Значение по умолчанию — wwwroot, которое сопоставляется с Resources/Raw/wwwroot.

Кроме того, HybridWebView определяет событие, которое возникает RawMessageReceived при получении необработанного сообщения. Объект HybridWebViewRawMessageReceivedEventArgs, который сопровождает событие, определяет свойство Message, содержащее сообщение.

Код C# вашего приложения может вызывать синхронные и асинхронные методы JavaScript в HybridWebView с помощью методов InvokeJavaScriptAsync и EvaluateJavaScriptAsync. Код JavaScript приложения также может вызывать синхронные и асинхронные методы C#. Дополнительные сведения см. в разделе "Вызов JavaScript" из C# и вызов C# из JavaScript.

Чтобы создать приложение .NET MAUI с помощью HybridWebView, вам необходимо:

  • Веб-содержимое приложения, состоящее из статического HTML, JavaScript, CSS, изображений и других файлов.
  • Элемент HybridWebView управления в составе пользовательского интерфейса приложения. Это можно сделать, ссылаясь на него в XAML приложения.
  • Код в веб-содержимом и в C#/.NET, который использует HybridWebView API для отправки сообщений между двумя компонентами.

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

Внимание

По умолчанию элемент HybridWebView управления не будет доступен, если включен полный тримминг или Native AOT. Сведения об изменении этого поведения см. в разделе "Параметры функции обрезки".

Создание приложения .NET MAUI HybridWebView

Создание приложения .NET MAUI с помощью HybridWebView:

  1. Откройте существующий проект приложения .NET MAUI или создайте проект приложения .NET MAUI.

  2. Добавьте веб-содержимое в проект приложения .NET MAUI.

    Веб-содержимое приложения должно быть включено в проект .NET MAUI в качестве необработанных ресурсов. Сырой ресурс — это любой файл в папке приложения Resources\Raw и включает вложенные папки. По умолчанию HybridWebViewвеб-содержимое должно быть помещено в папку Resources\Raw\wwwroot с основным файлом с именем index.html.

    Простое приложение может содержать следующие файлы и содержимое:

    • Resources\Raw\wwwroot\index.html с содержимым для основного пользовательского интерфейса:

      <!DOCTYPE html>
      
      <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
      <head>
          <meta charset="utf-8" />
          <title></title>
          <link rel="icon" href="data:,">
          <link rel="stylesheet" href="styles/app.css">
          <script src="scripts/HybridWebView.js"></script>
          <script>
              function LogMessage(msg) {
                  var messageLog = document.getElementById("messageLog");
                  messageLog.value += '\r\n' + msg;
              }
      
              window.addEventListener(
                  "HybridWebViewMessageReceived",
                  function (e) {
                      LogMessage("Raw message: " + e.detail.message);
                  });
      
              function AddNumbers(a, b) {
                  var result = {
                      "result": a + b,
                      "operationName": "Addition"
                  };
                  return result;
              }
      
              var count = 0;
      
              async function EvaluateMeWithParamsAndAsyncReturn(s1, s2) {
                  const response = await fetch("/asyncdata.txt");
                  if (!response.ok) {
                      throw new Error(`HTTP error: ${response.status}`);
                  }
                  var jsonData = await response.json();
      
                  jsonData[s1] = s2;
      
                  const msg = 'JSON data is available: ' + JSON.stringify(jsonData);
                  window.HybridWebView.SendRawMessage(msg)
      
                  return jsonData;
              }
      
              async function InvokeDoSyncWork() {
                  LogMessage("Invoking DoSyncWork");
                  await window.HybridWebView.InvokeDotNet('DoSyncWork');
                  LogMessage("Invoked DoSyncWork");
              }
      
              async function InvokeDoSyncWorkParams() {
                  LogMessage("Invoking DoSyncWorkParams");
                  await window.HybridWebView.InvokeDotNet('DoSyncWorkParams', [123, 'hello']);
                  LogMessage("Invoked DoSyncWorkParams");
              }
      
              async function InvokeDoSyncWorkReturn() {
                  LogMessage("Invoking DoSyncWorkReturn");
                  const retValue = await window.HybridWebView.InvokeDotNet('DoSyncWorkReturn');
                  LogMessage("Invoked DoSyncWorkReturn, return value: " + retValue);
              }
      
              async function InvokeDoSyncWorkParamsReturn() {
                  LogMessage("Invoking DoSyncWorkParamsReturn");
                  const retValue = await window.HybridWebView.InvokeDotNet('DoSyncWorkParamsReturn', [123, 'hello']);
                  LogMessage("Invoked DoSyncWorkParamsReturn, return value: message=" + retValue.Message + ", value=" + retValue.Value);
              }
      
              async function InvokeDoAsyncWork() {
                  LogMessage("Invoking DoAsyncWork");
                  await window.HybridWebView.InvokeDotNet('DoAsyncWork');
                  LogMessage("Invoked DoAsyncWork");
              }
      
              async function InvokeDoAsyncWorkParams() {
                  LogMessage("Invoking DoAsyncWorkParams");
                  await window.HybridWebView.InvokeDotNet('DoAsyncWorkParams', [123, 'hello']);
                  LogMessage("Invoked DoAsyncWorkParams");
              }
      
              async function InvokeDoAsyncWorkReturn() {
                  LogMessage("Invoking DoAsyncWorkReturn");
                  const retValue = await window.HybridWebView.InvokeDotNet('DoAsyncWorkReturn');
                  LogMessage("Invoked DoAsyncWorkReturn, return value: " + retValue);
              }
      
              async function InvokeDoAsyncWorkParamsReturn() {
                  LogMessage("Invoking DoAsyncWorkParamsReturn");
                  const retValue = await window.HybridWebView.InvokeDotNet('DoAsyncWorkParamsReturn', [123, 'hello']);
                  LogMessage("Invoked DoAsyncWorkParamsReturn, return value: message=" + retValue.Message + ", value=" + retValue.Value);
              }                
      
          </script>
      </head>
      <body>
          <div>
              Hybrid sample!
          </div>
          <div>
              <button onclick="window.HybridWebView.SendRawMessage('Message from JS! ' + (count++))">Send message to C#</button>
          </div>
          <div>
              <button onclick="InvokeDoSyncWork()">Call C# sync method (no params)</button>
              <button onclick="InvokeDoSyncWorkParams()">Call C# sync method (params)</button>
              <button onclick="InvokeDoSyncWorkReturn()">Call C# method (no params) and get simple return value</button>
              <button onclick="InvokeDoSyncWorkParamsReturn()">Call C# method (params) and get complex return value</button>
          </div>
          <div>
              <button onclick="InvokeDoAsyncWork()">Call C# async method (no params)</button>
              <button onclick="InvokeDoAsyncWorkParams()">Call C# async method (params)</button>
              <button onclick="InvokeDoAsyncWorkReturn()">Call C# async method (no params) and get simple return value</button>
              <button onclick="InvokeDoAsyncWorkParamsReturn()">Call C# async method (params) and get complex return value</button>
          </div>            
          <div>
              Log: <textarea readonly id="messageLog" style="width: 80%; height: 10em;"></textarea>
          </div>
          <div>
              Consider checking out this PDF: <a href="docs/sample.pdf">sample.pdf</a>
          </div>
      </body>
      </html>
      
    • Resources\Raw\wwwroot\scripts\HybridWebView.js со стандартной HybridWebView библиотекой JavaScript:

      window.HybridWebView = {
          "Init": function Init() {
              function DispatchHybridWebViewMessage(message) {
                  const event = new CustomEvent("HybridWebViewMessageReceived", { detail: { message: message } });
                  window.dispatchEvent(event);
              }
      
              if (window.chrome && window.chrome.webview) {
                  // Windows WebView2
                  window.chrome.webview.addEventListener('message', arg => {
                      DispatchHybridWebViewMessage(arg.data);
                  });
              }
              else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
                  // iOS and MacCatalyst WKWebView
                  window.external = {
                      "receiveMessage": message => {
                          DispatchHybridWebViewMessage(message);
                      }
                  };
              }
              else {
                  // Android WebView
                  window.addEventListener('message', arg => {
                      DispatchHybridWebViewMessage(arg.data);
                  });
              }
          },
      
          "SendRawMessage": function SendRawMessage(message) {
              window.HybridWebView.__SendMessageInternal('__RawMessage', message);
          },
      
          "InvokeDotNet": async function InvokeDotNetAsync(methodName, paramValues) {
              const body = {
                  MethodName: methodName
              };
      
              if (typeof paramValues !== 'undefined') {
                  if (!Array.isArray(paramValues)) {
                      paramValues = [paramValues];
                  }
      
                  for (var i = 0; i < paramValues.length; i++) {
                      paramValues[i] = JSON.stringify(paramValues[i]);
                  }
      
                  if (paramValues.length > 0) {
                      body.ParamValues = paramValues;
                  }
              }
      
              const message = JSON.stringify(body);
      
              var requestUrl = `${window.location.origin}/__hwvInvokeDotNet?data=${encodeURIComponent(message)}`;
      
              const rawResponse = await fetch(requestUrl, {
                  method: 'GET',
                  headers: {
                      'Accept': 'application/json'
                  }
              });
              const response = await rawResponse.json();
      
              if (response) {
                  if (response.IsJson) {
                      return JSON.parse(response.Result);
                  }
      
                  return response.Result;
              }
      
              return null;
          },
      
          "__SendMessageInternal": function __SendMessageInternal(type, message) {
      
              const messageToSend = type + '|' + message;
      
              if (window.chrome && window.chrome.webview) {
                  // Windows WebView2
                  window.chrome.webview.postMessage(messageToSend);
              }
              else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
                  // iOS and MacCatalyst WKWebView
                  window.webkit.messageHandlers.webwindowinterop.postMessage(messageToSend);
              }
              else {
                  // Android WebView
                  hybridWebViewHost.sendMessage(messageToSend);
              }
          },
      
          "__InvokeJavaScript": async function __InvokeJavaScript(taskId, methodName, args) {
              try {
                  var result = null;
                  if (methodName[Symbol.toStringTag] === 'AsyncFunction') {
                      result = await methodName(...args);
                  } else {
                      result = methodName(...args);
                  }
                  window.HybridWebView.__TriggerAsyncCallback(taskId, result);
              } catch (ex) {
                  console.error(ex);
                  window.HybridWebView.__TriggerAsyncFailedCallback(taskId, ex);
              }
          },
      
          "__TriggerAsyncCallback": function __TriggerAsyncCallback(taskId, result) {
              const json = JSON.stringify(result);
              window.HybridWebView.__SendMessageInternal('__InvokeJavaScriptCompleted', taskId + '|' + json);
          },
      
          "__TriggerAsyncFailedCallback": function __TriggerAsyncCallback(taskId, error) {
      
              if (!error) {
                  json = {
                      Message: "Unknown error",
                      StackTrace: Error().stack
                  };
              } else if (error instanceof Error) {
                  json = {
                      Name: error.name,
                      Message: error.message,
                      StackTrace: error.stack
                  };
              } else if (typeof (error) === 'string') {
                  json = {
                      Message: error,
                      StackTrace: Error().stack
                  };
              } else {
                  json = {
                      Message: JSON.stringify(error),
                      StackTrace: Error().stack
                  };
              }
      
              json = JSON.stringify(json);
              window.HybridWebView.__SendMessageInternal('__InvokeJavaScriptFailed', taskId + '|' + json);
          }
      }
      
      window.HybridWebView.Init();
      

    Затем добавьте в проект любое дополнительное веб-содержимое.

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

    В некоторых случаях Visual Studio может добавлять некорректные записи в файл .csproj проекта. При использовании расположения по умолчанию для необработанных ресурсов не должно быть никаких записей для этих файлов или папок в CSPROJ-файле .

  3. Добавьте элемент управления HybridWebView в ваше приложение.

    <Grid RowDefinitions="Auto,*"
          ColumnDefinitions="*">
        <Button Text="Send message to JavaScript"
                Clicked="OnSendMessageButtonClicked" />
        <HybridWebView x:Name="hybridWebView"
                       RawMessageReceived="OnHybridWebViewRawMessageReceived"
                       Grid.Row="1" />
    </Grid>
    
  4. Измените метод CreateMauiApp класса MauiProgram, чтобы включить средства разработчика в элементах управления WebView, когда приложение выполняется в конфигурации отладки. Для этого вызовите AddHybridWebViewDeveloperTools метод объекта IServiceCollection :

    using Microsoft.Extensions.Logging;
    
    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });
    
    #if DEBUG
            builder.Services.AddHybridWebViewDeveloperTools();
            builder.Logging.AddDebug();            
    #endif
            // Register any app services on the IServiceCollection object
    
            return builder.Build();
        }
    }
    
  5. HybridWebView Используйте API для отправки сообщений между кодом JavaScript и C#:

    private void OnSendMessageButtonClicked(object sender, EventArgs e)
    {
        hybridWebView.SendRawMessage($"Hello from C#!");
    }
    
    private async void OnHybridWebViewRawMessageReceived(object sender, HybridWebViewRawMessageReceivedEventArgs e)
    {
        await DisplayAlert("Raw Message Received", e.Message, "OK");
    }
    
    private void OnSendMessageButtonClicked(object sender, EventArgs e)
    {
        hybridWebView.SendRawMessage($"Hello from C#!");
    }
    
    private async void OnHybridWebViewRawMessageReceived(object sender, HybridWebViewRawMessageReceivedEventArgs e)
    {
        await DisplayAlertAsync("Raw Message Received", e.Message, "OK");
    }
    

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

Вызов JavaScript из C#

Код C# вашего приложения может синхронно и асинхронно вызывать методы JavaScript внутри HybridWebView, с необязательными параметрами и необязательным возвращаемым значением. Это можно сделать с помощью методов InvokeJavaScriptAsync и EvaluateJavaScriptAsync.

  • Метод EvaluateJavaScriptAsync запускает код JavaScript, предоставленный с помощью параметра, и возвращает результат в виде строки.
  • Метод InvokeJavaScriptAsync вызывает указанный метод JavaScript, при необходимости передавая значения параметров, и задает универсальный аргумент, указывающий тип возвращаемого значения. Он возвращает объект универсального типа аргумента, который содержит возвращаемое значение вызываемого метода JavaScript. Внутренние параметры и возвращаемые значения кодируются в формате JSON.

Примечание.

.NET 10 включает перегрузку InvokeJavaScriptAsync, которая вызывает указанный метод JavaScript без указания каких-либо сведений о типе возврата. Дополнительные сведения см. в статье Вызов методов JavaScript, которые не возвращают значение.

Вызов синхронного JavaScript

Синхронные методы JavaScript можно вызывать с помощью методов EvaluateJavaScriptAsync и InvokeJavaScriptAsync. В следующем примере InvokeJavaScriptAsync метод используется для демонстрации вызова JavaScript, внедренного в веб-содержимое приложения. Например, простой метод Javascript для добавления двух чисел можно определить в веб-содержимом:

function AddNumbers(a, b) {
    return a + b;
}

Метод AddNumbers JavaScript можно вызвать из C# с InvokeJavaScriptAsync помощью метода:

double x = 123d;
double y = 321d;

double result = await hybridWebView.InvokeJavaScriptAsync<double>(
    "AddNumbers", // JavaScript method name
    HybridSampleJSContext.Default.Double, // JSON serialization info for return type
    [x, y], // Parameter values
    [HybridSampleJSContext.Default.Double, HybridSampleJSContext.Default.Double]); // JSON serialization info for each parameter

Вызов метода требует указания JsonTypeInfo объектов, включающих сведения о сериализации для типов, используемых в операции. Эти объекты создаются автоматически, включая следующий partial класс в проекте:

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(double))]
internal partial class HybridSampleJsContext : JsonSerializerContext
{
    // This type's attributes specify JSON serialization info to preserve type structure
    // for trimmed builds.
}

Внимание

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

Вызов асинхронного JavaScript

Асинхронные методы JavaScript можно вызывать с помощью EvaluateJavaScriptAsync методов и InvokeJavaScriptAsync методов. В следующем примере InvokeJavaScriptAsync метод используется для демонстрации вызова JavaScript, внедренного в веб-содержимое приложения. Например, метод Javascript, который асинхронно извлекает данные, можно определить в веб-содержимом:

async function EvaluateMeWithParamsAndAsyncReturn(s1, s2) {
    const response = await fetch("/asyncdata.txt");
    if (!response.ok) {
            throw new Error(`HTTP error: ${response.status}`);
    }
    var jsonData = await response.json();
    jsonData[s1] = s2;

    return jsonData;
}

Метод EvaluateMeWithParamsAndAsyncReturn JavaScript можно вызвать из C# с InvokeJavaScriptAsync помощью метода:

Dictionary<string, string> asyncResult = await hybridWebView.InvokeJavaScriptAsync<Dictionary<string, string>>(
    "EvaluateMeWithParamsAndAsyncReturn", // JavaScript method name
    HybridSampleJSContext.Default.DictionaryStringString, // JSON serialization info for return type
    ["new_key", "new_value"], // Parameter values
    [HybridSampleJSContext.Default.String, HybridSampleJSContext.Default.String]); // JSON serialization info for each parameter

В этом примере asyncResult является Dictionary<string, string>, содержащим данные JSON из веб-запроса.

Вызов метода требует указания JsonTypeInfo объектов, включающих сведения о сериализации для типов, используемых в операции. Эти объекты создаются автоматически, включая следующий partial класс в проекте:

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Dictionary<string, string>))]
[JsonSerializable(typeof(string))]
internal partial class HybridSampleJSContext : JsonSerializerContext
{
    // This type's attributes specify JSON serialization info to preserve type structure
    // for trimmed builds.  
}

Внимание

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

Вызов методов JavaScript, которые не возвращают значение

Метод InvokeJavaScriptAsync также можно использовать для вызова методов JavaScript, которые не возвращают значение. Существуют альтернативные подходы к этому:

  • Вызовите InvokeJavaScriptAsync, указав имя метода JavaScript и любые необязательные параметры:

    await hybridWebView.InvokeJavaScriptAsync("javaScriptWithVoidReturn"); // JavaScript method name
    

    В этом примере указывается только имя метода JavaScript.

  • Вызов метода InvokeJavaScriptAsync без указания универсального аргумента:

    await hybridWebView.InvokeJavaScriptAsync(
         "javaScriptWithParamsAndVoidReturn",  // JavaScript method name
         HybridSampleJSContext.Default.Double, // JSON serialization info for return type
         [x, y], // Parameter values
         [HybridSampleJSContext.Default.Double, HybridSampleJSContext.Default.Double]); // JSON serialization info for each parameter
    

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

  • Вызовите метод InvokeJavaScriptAsync при указании универсального аргумента:

    await hybridWebView.InvokeJavaScriptAsync<double>(
        "javaScriptWithParamsAndVoidReturn", // JavaScript method name
        null, // JSON serialization info for return type
        [x, y], // Parameter values
        [HybridSampleJSContext.Default.Double, HybridSampleJSContext.Default.Double]); // JSON serialization info for each parameter
    

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

Отправка исключений JavaScript в .NET

По умолчанию вызов методов JavaScript в HybridWebView может скрывать исключения, создаваемые кодом JavaScript. Чтобы включить отправку исключений JavaScript в .NET, где они перебрасываются как исключения .NET, добавьте следующий код в класс MauiProgram:

static MauiProgram()
{
    AppContext.SetSwitch("HybridWebView.InvokeJavaScriptThrowsExceptions", true);
}

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

Это позволяет создавать сценарии, в которых если ваш код C# вызывает код JavaScript, и код JavaScript завершится сбоем, то ошибка выполнения JavaScript будет отправлена в .NET, где она будет повторно выброшена как исключение .NET, которое может быть перехвачено и обработано.

Вызов C# из JavaScript

Код JavaScript приложения в HybridWebView может синхронно и асинхронно вызывать методы C# с необязательными параметрами и необязательным возвращаемым значением. Это выполняется посредством следующих настроек.

  • Определение общедоступных методов C#, которые будут вызываться из JavaScript.
  • Вызов метода SetInvokeJavaScriptTarget для задания объекта, который будет целевым объектом вызовов JavaScript из HybridWebView.
  • Вызов методов C# из JavaScript.

В следующем примере определяются общедоступные синхронные и асинхронные методы для вызова из JavaScript:

public partial class MainPage : ContentPage
{
    ...  

    public void DoSyncWork()
    {
        Debug.WriteLine("DoSyncWork");
    }

    public void DoSyncWorkParams(int i, string s)
    {
        Debug.WriteLine($"DoSyncWorkParams: {i}, {s}");
    }

    public string DoSyncWorkReturn()
    {
        Debug.WriteLine("DoSyncWorkReturn");
        return "Hello from C#!";
    }

    public SyncReturn DoSyncWorkParamsReturn(int i, string s)
    {
        Debug.WriteLine($"DoSyncWorkParamReturn: {i}, {s}");
        return new SyncReturn
        {
            Message = "Hello from C#!" + s,
            Value = i
        };
    }

    public async Task DoAsyncWork()
    {
        Debug.WriteLine("DoAsyncWork");
        await Task.Delay(1000);
    }

    public async Task DoAsyncWorkParams(int i, string s)
    {
        Debug.WriteLine($"DoAsyncWorkParams: {i}, {s}");
        await Task.Delay(1000);
    }

    public async Task<String> DoAsyncWorkReturn()
    {
        Debug.WriteLine("DoAsyncWorkReturn");
        await Task.Delay(1000);
        return "Hello from C#!";
    }

    public async Task<SyncReturn> DoAsyncWorkParamsReturn(int i, string s)
    {
        Debug.WriteLine($"DoAsyncWorkParamsReturn: {i}, {s}");
        await Task.Delay(1000);
        return new SyncReturn
        {
            Message = "Hello from C#!" + s,
            Value = i
        };
    }    

    public class SyncReturn
    {
        public string? Message { get; set; }
        public int Value { get; set; }
    }  
}

Затем необходимо вызвать SetInvokeJavaScriptTarget метод, чтобы задать объект, который будет целевым объектом вызовов JavaScript из HybridWebView:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        hybridWebView.SetInvokeJavaScriptTarget(this);
    }
    ...
}

Методы, доступные в объекте, установленном с помощью метода SetInvokeJavaScriptTarget, можно вызвать из JavaScript с использованием функции window.HybridWebView.InvokeDotNet.

// Synchronous methods
await window.HybridWebView.InvokeDotNet('DoSyncWork');
await window.HybridWebView.InvokeDotNet('DoSyncWorkParams', [123, 'hello']);
const retValue = await window.HybridWebView.InvokeDotNet('DoSyncWorkReturn');
const retValue = await window.HybridWebView.InvokeDotNet('DoSyncWorkParamsReturn', [123, 'hello']);

// Asynchronous methods
await window.HybridWebView.InvokeDotNet('DoAsyncWork');
await window.HybridWebView.InvokeDotNet('DoAsyncWorkParams', [123, 'hello']);
const retValue = await window.HybridWebView.InvokeDotNet('DoAsyncWorkReturn');
const retValue = await window.HybridWebView.InvokeDotNet('DoAsyncWorkParamsReturn', [123, 'hello']);

Функция window.HybridWebView.InvokeDotNet JavaScript вызывает указанный метод C# с необязательными параметрами и необязательным возвращаемым значением.

Примечание.

window.HybridWebView.InvokeDotNet Вызов функции JavaScript требует, чтобы приложение включало библиотеку JavaScript HybridWebView.js, указанную ранее в этой статье.