From 938870e0fecfa0ad5cb3fbe3a0ad42657a936609 Mon Sep 17 00:00:00 2001 From: David Britch Date: Thu, 14 Nov 2024 11:02:49 +0000 Subject: [PATCH 1/2] Call .NET methods from JS --- .../HybridWebViewDemo/HybridWebViewDemo.sln | 1 + .../HybridWebViewDemo/MainPage.xaml.cs | 50 +++++++++++++++- .../HybridWebViewDemo/MauiProgram.cs | 3 +- .../Resources/Raw/wwwroot/index.html | 48 +++++++++++++-- .../Raw/wwwroot/scripts/HybridWebView.js | 58 ++++++++++++++++--- 5 files changed, 142 insertions(+), 18 deletions(-) diff --git a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo.sln b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo.sln index e2a6389b7..64a3da168 100644 --- a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo.sln +++ b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo.sln @@ -13,6 +13,7 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {AA468903-C211-421B-A09A-81F3745FD28B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AA468903-C211-421B-A09A-81F3745FD28B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA468903-C211-421B-A09A-81F3745FD28B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU {AA468903-C211-421B-A09A-81F3745FD28B}.Release|Any CPU.ActiveCfg = Release|Any CPU {AA468903-C211-421B-A09A-81F3745FD28B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection diff --git a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MainPage.xaml.cs b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MainPage.xaml.cs index 747bcb602..2416c7628 100644 --- a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MainPage.xaml.cs +++ b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MainPage.xaml.cs @@ -1,4 +1,5 @@ -using System.Text.Json.Serialization; +using System.Diagnostics; +using System.Text.Json.Serialization; namespace HybridWebViewDemo; @@ -9,6 +10,7 @@ public partial class MainPage : ContentPage public MainPage() { InitializeComponent(); + hybridWebView.SetInvokeJavaScriptTarget(new DotNetMethods(this)); } private void OnSendMessageButtonClicked(object sender, EventArgs e) @@ -22,7 +24,7 @@ private async void OnInvokeJSMethodButtonClicked(object sender, EventArgs e) double x = 123d; double y = 321d; - ComputationResult result = await hybridWebView.InvokeJavaScriptAsync( + ComputationResult? result = await hybridWebView.InvokeJavaScriptAsync( "AddNumbers", // JavaScript method name HybridSampleJSContext.Default.ComputationResult, // JSON serialization info for return type [x, y], // Parameter values @@ -40,7 +42,7 @@ private async void OnInvokeAsyncJSMethodButtonClicked(object sender, EventArgs e { string statusResult = string.Empty; - Dictionary asyncResult = await hybridWebView.InvokeJavaScriptAsync>( + Dictionary? asyncResult = await hybridWebView.InvokeJavaScriptAsync>( "EvaluateMeWithParamsAndAsyncReturn", // JavaScript method name HybridSampleJSContext.Default.DictionaryStringString, // JSON serialization info for return type ["new_key", "new_value"], // Parameter values @@ -75,4 +77,46 @@ internal partial class HybridSampleJSContext : JsonSerializerContext // This type's attributes specify JSON serialization info to preserve type structure // for trimmed builds. } + + private class DotNetMethods + { + MainPage _mainPage; + + public DotNetMethods(MainPage mainPage) + { + _mainPage = mainPage; + } + + 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 class SyncReturn + { + public string? Message { get; set; } + public int Value { get; set; } + } } diff --git a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MauiProgram.cs b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MauiProgram.cs index 5c5a1cd61..ca612f207 100644 --- a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MauiProgram.cs +++ b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MauiProgram.cs @@ -16,7 +16,8 @@ public static MauiApp CreateMauiApp() }); #if DEBUG - builder.Logging.AddDebug(); + builder.Services.AddHybridWebViewDeveloperTools(); + builder.Logging.AddDebug(); #endif return builder.Build(); diff --git a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/Resources/Raw/wwwroot/index.html b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/Resources/Raw/wwwroot/index.html index 1b52185db..d0b48f664 100644 --- a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/Resources/Raw/wwwroot/index.html +++ b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/Resources/Raw/wwwroot/index.html @@ -8,11 +8,15 @@ @@ -49,10 +79,16 @@
- Message from C#: + + + + +
+
+ Log:
- Consider examining this PDF: sample.pdf + Consider checking out this PDF: sample.pdf
- + \ No newline at end of file diff --git a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/Resources/Raw/wwwroot/scripts/HybridWebView.js b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/Resources/Raw/wwwroot/scripts/HybridWebView.js index 337c388ce..62023e234 100644 --- a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/Resources/Raw/wwwroot/scripts/HybridWebView.js +++ b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/Resources/Raw/wwwroot/scripts/HybridWebView.js @@ -1,5 +1,5 @@ window.HybridWebView = { - "Init": function () { + "Init": function Init() { function DispatchHybridWebViewMessage(message) { const event = new CustomEvent("HybridWebViewMessageReceived", { detail: { message: message } }); window.dispatchEvent(event); @@ -27,11 +27,53 @@ } }, - "SendRawMessage": function (message) { - window.HybridWebView.__SendMessageInternal('RawMessage', message); + "SendRawMessage": function SendRawMessage(message) { + window.HybridWebView.__SendMessageInternal('__RawMessage', message); }, - "__SendMessageInternal": function (type, 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; @@ -49,7 +91,7 @@ } }, - "InvokeMethod": function (taskId, methodName, args) { + "__InvokeJavaScript": function __InvokeJavaScript(taskId, methodName, args) { if (methodName[Symbol.toStringTag] === 'AsyncFunction') { // For async methods, we need to call the method and then trigger the callback when it's done const asyncPromise = methodName(...args); @@ -65,14 +107,14 @@ } }, - "__TriggerAsyncCallback": function (taskId, result) { + "__TriggerAsyncCallback": function __TriggerAsyncCallback(taskId, result) { // Make sure the result is a string if (result && typeof (result) !== 'string') { result = JSON.stringify(result); } - window.HybridWebView.__SendMessageInternal('InvokeMethodCompleted', taskId + '|' + result); + window.HybridWebView.__SendMessageInternal('__InvokeJavaScriptCompleted', taskId + '|' + result); } } -window.HybridWebView.Init(); +window.HybridWebView.Init(); \ No newline at end of file From a9c0ed249d6b3cd15084e4f0134d2504179675e5 Mon Sep 17 00:00:00 2001 From: David Britch Date: Thu, 14 Nov 2024 15:02:16 +0000 Subject: [PATCH 2/2] Simplify code. --- .../HybridWebViewDemo/MainPage.xaml.cs | 64 ++++++++----------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MainPage.xaml.cs b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MainPage.xaml.cs index 2416c7628..12ce64cb2 100644 --- a/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MainPage.xaml.cs +++ b/9.0/UserInterface/Views/HybridWebViewDemo/HybridWebViewDemo/MainPage.xaml.cs @@ -10,7 +10,7 @@ public partial class MainPage : ContentPage public MainPage() { InitializeComponent(); - hybridWebView.SetInvokeJavaScriptTarget(new DotNetMethods(this)); + hybridWebView.SetInvokeJavaScriptTarget(this); } private void OnSendMessageButtonClicked(object sender, EventArgs e) @@ -61,6 +61,32 @@ private void hybridWebView_RawMessageReceived(object sender, HybridWebViewRawMes Dispatcher.Dispatch(() => editor.Text += Environment.NewLine + e.Message); } + 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 class ComputationResult { public double result { get; set; } @@ -78,42 +104,6 @@ internal partial class HybridSampleJSContext : JsonSerializerContext // for trimmed builds. } - private class DotNetMethods - { - MainPage _mainPage; - - public DotNetMethods(MainPage mainPage) - { - _mainPage = mainPage; - } - - 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 class SyncReturn { public string? Message { get; set; }