EJL.MauiHybridWebView 1.0.0-preview2

This is a prerelease version of EJL.MauiHybridWebView.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package EJL.MauiHybridWebView --version 1.0.0-preview2                
NuGet\Install-Package EJL.MauiHybridWebView -Version 1.0.0-preview2                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EJL.MauiHybridWebView" Version="1.0.0-preview2" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add EJL.MauiHybridWebView --version 1.0.0-preview2                
#r "nuget: EJL.MauiHybridWebView, 1.0.0-preview2"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install EJL.MauiHybridWebView as a Cake Addin
#addin nuget:?package=EJL.MauiHybridWebView&version=1.0.0-preview2&prerelease

// Install EJL.MauiHybridWebView as a Cake Tool
#tool nuget:?package=EJL.MauiHybridWebView&version=1.0.0-preview2&prerelease                

.NET MAUI HybridWebView experiment

This repo has the experimental .NET MAUI HybridWebView control, which enables hosting arbitrary HTML/JS/CSS content in a WebView and enables communication between the code in the WebView (JavaScript) and the code that hosts the WebView (C#/.NET). For example, if you have an existing React JS application, you could host it in a cross-platform .NET MAUI native application, and build the back-end of the application using C# and .NET.

Example usage of the control:

<hwv:HybridWebView
    HybridAssetRoot="hybrid_root"
    MainFile="hybrid_app.html"
    RawMessageReceived="OnHybridWebViewRawMessageReceived" />

And here's how .NET code can call a JavaScript method:

var sum = await myHybridWebView.InvokeJsMethodAsync<int>("JsAddNumbers", 123, 456);

And the reverse, JavaScript code calling a .NET method:

HybridWebView.SendInvokeMessageToDotNet("CallMeFromScript", ["msg from js", 987]);

In addition to method invocation, sending "raw" messages is also supported.

What's in this repo?

Projects in this repo:

  • HybridWebView --> a cross-platform .NET MAUI control that can load static web assets (HTML, JS, CSS, etc.) and send messages between JavaScript and .NET
  • MauiCSharpInteropWebView --> a sample app that shows the basic functionality of sending messages and calling methods between JavaScript and .NET
  • MauiReactJSHybridApp --> a sample app that incorporates a pre-existing React-based todo application into a .NET MAUI cross-platform application

Discussions/questions/comments

See the main discussion topic here: https://github.com/dotnet/maui/discussions/12009

Or please log an issue in this repo for any other topics.

Getting Started

To get started, you'll need a .NET MAUI 7 project, then add the HybridWebView control, and add some web content to it.

Note: If you'd like to check out an already completed sample, go to https://github.com/Eilon/SampleMauiHybridWebViewProject

  1. Ensure you have Visual Studio 2022 with the .NET MAUI workload installed
  2. Create a .NET MAUI App project that targets .NET 7 (or use an existing one)
  3. Add a reference to the EJL.MauiHybridWebView package:
    1. Right-click on the Dependencies node in Solution Explorer and select Manage NuGet Packages
    2. Select the Browse tab
    3. Ensure the Include prerelease checkbox is checked
    4. In the search box enter ejl.mauihybridwebview
    5. Select the matching package, and click the Install button
  4. Register and add the HybridWebView control to a page in your app:
    1. In MauiProgram.cs add the line builder.Services.AddHybridWebView(); to register the HybridWebView components
    2. Open the MainPage.xaml file
    3. Delete the <ScrollView> control and all of its contents
    4. Add a xmlns:ejl="clr-namespace:HybridWebView;assembly=HybridWebView" declaration to the top-level <ContentPage ....> tag
    5. Add the markup <ejl:HybridWebView HybridAssetRoot="hybrid_root" MainFile="index.html" RawMessageReceived="OnHybridWebViewRawMessageReceived" /> inside the <ContentPage> tag
    6. Open the MainPage.xaml.cs file
    7. Delete the count field, and the OnCounterClicked method, and replace it with the following code:
      private async void OnHybridWebViewRawMessageReceived(object sender, HybridWebView.HybridWebViewRawMessageReceivedEventArgs e)
      {
          await Dispatcher.DispatchAsync(async () =>
          {
              await DisplayAlert("JavaScript message", e.Message, "OK");
          });
      }
      
  5. Now add some web content to the app:
    1. In Solution Explorer expand the Resources / Raw folder
    2. Create a new sub-folder called hybrid_root
    3. In the hybrid_root folder add a new file called index.html and replace its contents with:
      <!DOCTYPE html>
      
      <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
      <head>
          <meta charset="utf-8" />
          <title></title>
          <script src="HybridWebView.js"></script>
          <script src="myapp.js"></script>
      </head>
      <body>
          <div>
              Your message: <input type="text" id="messageInput" />
          </div>
          <div>
              <button onclick="SendMessageToCSharp()">Send to C#!</button>
          </div>
      </body>
      </html>
      
    4. In the same folder add another file myapp.js with the following contents:
      function SendMessageToCSharp() {
          var message = document.getElementById('messageInput').value;
          HybridWebView.SendRawMessageToDotNet(message);
      }
      
    5. Add one last file named HybridWebView.js with the following contents:
      // Standard methods for HybridWebView
      
      window.HybridWebView = {
          "SendRawMessageToDotNet": function SendRawMessageToDotNet(message) {
              window.HybridWebView.SendMessageToDotNet(0, message);
          },
      
          "SendInvokeMessageToDotNet": function SendInvokeMessageToDotNet(methodName, paramValues) {
              if (typeof paramValues !== 'undefined') {
                  if (!Array.isArray(paramValues)) {
                      paramValues = [paramValues];
                  }
                  for (var i = 0; i < paramValues.length; i++) {
                      paramValues[i] = JSON.stringify(paramValues[i]);
                  }
              }
      
              window.HybridWebView.SendMessageToDotNet(1, JSON.stringify({ "MethodName": methodName, "ParamValues": paramValues }));
          },
      
          "SendMessageToDotNet": function SendMessageToDotNet(messageType, messageContent) {
              var message = JSON.stringify({ "MessageType": messageType, "MessageContent": messageContent });
      
              if (window.chrome && window.chrome.webview) {
                  // Windows WebView2
                  window.chrome.webview.postMessage(message);
              }
              else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop)
              {
                  // iOS and MacCatalyst WKWebView
                  window.webkit.messageHandlers.webwindowinterop.postMessage(message);
              }
              else {
                  // Android WebView
                  hybridWebViewHost.sendMessage(message);
              }
          }
      };
      
  6. You can now run your .NET MAUI app with the HybridWebView control!
    1. You can run it on Windows, Android, iOS, or macOS
    2. When you launch the app, type text into the textbox and click the button to receive the message in C# code

How to run the source code in this repo

To run this app you need to have Visual Studio for Windows or Mac, including the .NET MAUI workload. Then clone this repo, open the solution, and run one of the sample projects.

MauiReactJSHybridApp React JS app

The MauiReactJSHybridApp sample contains portions of a pre-existing Todo App built using React JS.

The original React JS Todo app sample used here is based on this sample: https://github.com/mdn/todo-react. I created a fork at https://github.com/Eilon/todo-react that incorporates some small changes to call the .NET API from JavaScript to synchronize the Todo list between the two parts of the app.

To make changes to the fork and update the .NET MAUI app, here's what I do:

  1. Clone of the forked repo and open a terminal/console window in that folder
  2. Run yarn to ensure the JavaScript dependencies are installed
  3. Run set PUBLIC_URL=/ to establish the root of the app as / because that's the root of the .NET MAUI HybridWebView app
  4. Run npm run build to compile the app and produce a static version of it
    • If you get this error: Error: error:0308010C:digital envelope routines::unsupported
    • Then run set NODE_OPTIONS=--openssl-legacy-provider
    • And run this again: npm run build
  5. This will build the HTML/JS/CSS output into a new ./build folder
  6. Go to the MauiReactJSHybridApp's Resources/Raw/ReactTodoApp folder and delete all the existing files, and replace with the files from the previous step's ./build folder
  7. Then run the MauiReactJSHybridApp from Visual Studio

This project is licensed under the MIT License. However, portions of the incorporated source code may be subject to other licenses:

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-android33.0 is compatible.  net7.0-ios was computed.  net7.0-ios16.1 is compatible.  net7.0-maccatalyst was computed.  net7.0-maccatalyst16.1 is compatible.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net7.0-windows10.0.19041 is compatible.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net7.0

    • No dependencies.
  • net7.0-android33.0

    • No dependencies.
  • net7.0-ios16.1

    • No dependencies.
  • net7.0-maccatalyst16.1

    • No dependencies.
  • net7.0-windows10.0.19041

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0-preview7 669 10/25/2024
1.0.0-preview6 8,416 3/12/2024
1.0.0-preview5 732 2/28/2024
1.0.0-preview4 8,606 9/19/2023
1.0.0-preview3 588 5/23/2023
1.0.0-preview2 369 4/13/2023
1.0.0-preview1 136 4/12/2023