diff --git a/src/Components/Server/src/Circuits/CircuitHost.cs b/src/Components/Server/src/Circuits/CircuitHost.cs index 15352805e377..29dc0bf2f625 100644 --- a/src/Components/Server/src/Circuits/CircuitHost.cs +++ b/src/Components/Server/src/Circuits/CircuitHost.cs @@ -404,7 +404,8 @@ public async Task DispatchEvent(string eventDescriptorJson, string eventArgsJson WebEventData webEventData; try { - webEventData = WebEventData.Parse(Renderer, eventDescriptorJson, eventArgsJson); + var jsonSerializerOptions = JSRuntime.ReadJsonSerializerOptions(); + webEventData = WebEventData.Parse(Renderer, jsonSerializerOptions, eventDescriptorJson, eventArgsJson); } catch (Exception ex) { diff --git a/src/Components/Server/src/Circuits/RemoteJSRuntime.cs b/src/Components/Server/src/Circuits/RemoteJSRuntime.cs index 3a3cb11d27c3..6239afae8708 100644 --- a/src/Components/Server/src/Circuits/RemoteJSRuntime.cs +++ b/src/Components/Server/src/Circuits/RemoteJSRuntime.cs @@ -28,6 +28,8 @@ public RemoteJSRuntime(IOptions options, ILogger JsonSerializerOptions; + internal void Initialize(CircuitClientProxy clientProxy) { _clientProxy = clientProxy ?? throw new ArgumentNullException(nameof(clientProxy)); diff --git a/src/Components/Shared/src/WebEventData.cs b/src/Components/Shared/src/WebEventData.cs index a281fbf44022..eed03b7a9d3f 100644 --- a/src/Components/Shared/src/WebEventData.cs +++ b/src/Components/Shared/src/WebEventData.cs @@ -15,7 +15,7 @@ internal class WebEventData { // This class represents the second half of parsing incoming event data, // once the event ID (and possibly the type of the eventArgs) becomes known. - public static WebEventData Parse(Renderer renderer, string eventDescriptorJson, string eventArgsJson) + public static WebEventData Parse(Renderer renderer, JsonSerializerOptions jsonSerializerOptions, string eventDescriptorJson, string eventArgsJson) { WebEventDescriptor eventDescriptor; try @@ -29,13 +29,14 @@ public static WebEventData Parse(Renderer renderer, string eventDescriptorJson, return Parse( renderer, + jsonSerializerOptions, eventDescriptor, eventArgsJson); } - public static WebEventData Parse(Renderer renderer, WebEventDescriptor eventDescriptor, string eventArgsJson) + public static WebEventData Parse(Renderer renderer, JsonSerializerOptions jsonSerializerOptions, WebEventDescriptor eventDescriptor, string eventArgsJson) { - var parsedEventArgs = ParseEventArgsJson(renderer, eventDescriptor.EventHandlerId, eventDescriptor.EventName, eventArgsJson); + var parsedEventArgs = ParseEventArgsJson(renderer, jsonSerializerOptions, eventDescriptor.EventHandlerId, eventDescriptor.EventName, eventArgsJson); return new WebEventData( eventDescriptor.BrowserRendererId, eventDescriptor.EventHandlerId, @@ -59,7 +60,7 @@ private WebEventData(int browserRendererId, ulong eventHandlerId, EventFieldInfo public EventArgs EventArgs { get; } - private static EventArgs ParseEventArgsJson(Renderer renderer, ulong eventHandlerId, string eventName, string eventArgsJson) + private static EventArgs ParseEventArgsJson(Renderer renderer, JsonSerializerOptions jsonSerializerOptions, ulong eventHandlerId, string eventName, string eventArgsJson) { try { @@ -70,7 +71,7 @@ private static EventArgs ParseEventArgsJson(Renderer renderer, ulong eventHandle // For custom events, the args type is determined from the associated delegate var eventArgsType = renderer.GetEventArgsType(eventHandlerId); - return (EventArgs)JsonSerializer.Deserialize(eventArgsJson, eventArgsType, JsonSerializerOptionsProvider.Options)!; + return (EventArgs)JsonSerializer.Deserialize(eventArgsJson, eventArgsType, jsonSerializerOptions)!; } catch (Exception e) { diff --git a/src/Components/WebAssembly/WebAssembly/src/Infrastructure/JSInteropMethods.cs b/src/Components/WebAssembly/WebAssembly/src/Infrastructure/JSInteropMethods.cs index d8acd6726663..58a96a783dea 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Infrastructure/JSInteropMethods.cs +++ b/src/Components/WebAssembly/WebAssembly/src/Infrastructure/JSInteropMethods.cs @@ -38,7 +38,8 @@ public static void NotifyLocationChanged(string uri, bool isInterceptedLink) public static Task DispatchEvent(WebEventDescriptor eventDescriptor, string eventArgsJson) { var renderer = RendererRegistry.Find(eventDescriptor.BrowserRendererId); - var webEvent = WebEventData.Parse(renderer, eventDescriptor, eventArgsJson); + var jsonSerializerOptions = DefaultWebAssemblyJSRuntime.Instance.ReadJsonSerializerOptions(); + var webEvent = WebEventData.Parse(renderer, jsonSerializerOptions, eventDescriptor, eventArgsJson); return renderer.DispatchEventAsync( webEvent.EventHandlerId, webEvent.EventFieldInfo, diff --git a/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.WarningSuppressions.xml b/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.WarningSuppressions.xml index 986fa0232bcd..c50d0425f4df 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.WarningSuppressions.xml +++ b/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.WarningSuppressions.xml @@ -35,7 +35,7 @@ ILLink IL2072 member - M:Microsoft.AspNetCore.Components.Web.WebEventData.ParseEventArgsJson(Microsoft.AspNetCore.Components.RenderTree.Renderer,System.UInt64,System.String,System.String) + M:Microsoft.AspNetCore.Components.Web.WebEventData.ParseEventArgsJson(Microsoft.AspNetCore.Components.RenderTree.Renderer,System.Text.Json.JsonSerializerOptions,System.UInt64,System.String,System.String) ILLink diff --git a/src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs b/src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs index 2ff3b6de080a..0453ce6f8c9f 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs +++ b/src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Text.Json; using Microsoft.JSInterop.Infrastructure; using Microsoft.JSInterop.WebAssembly; @@ -23,6 +24,8 @@ private DefaultWebAssemblyJSRuntime() JsonSerializerOptions.Converters.Add(new ElementReferenceJsonConverter(ElementReferenceContext)); } + public JsonSerializerOptions ReadJsonSerializerOptions() => JsonSerializerOptions; + // The following methods are invoke via Mono's JS interop mechanism (invoke_method) public static string? InvokeDotNet(string assemblyName, string methodIdentifier, string dotNetObjectId, string argsJson) { diff --git a/src/Components/WebView/WebView/src/IpcReceiver.cs b/src/Components/WebView/WebView/src/IpcReceiver.cs index f4b0c61a2f73..107ced59dbd1 100644 --- a/src/Components/WebView/WebView/src/IpcReceiver.cs +++ b/src/Components/WebView/WebView/src/IpcReceiver.cs @@ -88,7 +88,8 @@ private void EndInvokeJS(PageContext pageContext, long asyncHandle, bool succeed private Task DispatchBrowserEventAsync(PageContext pageContext, string eventDescriptor, string eventArgs) { var renderer = pageContext.Renderer; - var webEventData = WebEventData.Parse(renderer, eventDescriptor, eventArgs); + var jsonSerializerOptions = pageContext.JSRuntime.ReadJsonSerializerOptions(); + var webEventData = WebEventData.Parse(renderer, jsonSerializerOptions, eventDescriptor, eventArgs); return renderer.DispatchEventAsync( webEventData.EventHandlerId, webEventData.EventFieldInfo, diff --git a/src/Components/WebView/WebView/src/Services/WebViewJSRuntime.cs b/src/Components/WebView/WebView/src/Services/WebViewJSRuntime.cs index bb6b46ee6b6c..2f1e93d9fea2 100644 --- a/src/Components/WebView/WebView/src/Services/WebViewJSRuntime.cs +++ b/src/Components/WebView/WebView/src/Services/WebViewJSRuntime.cs @@ -23,6 +23,8 @@ public void AttachToWebView(IpcSender ipcSender) _ipcSender = ipcSender; } + public JsonSerializerOptions ReadJsonSerializerOptions() => JsonSerializerOptions; + protected override void BeginInvokeJS(long taskId, string identifier, string argsJson, JSCallResultType resultType, long targetInstanceId) { _ipcSender.BeginInvokeJS(taskId, identifier, argsJson, resultType, targetInstanceId); diff --git a/src/Components/test/E2ETest/Tests/EventCustomArgsTest.cs b/src/Components/test/E2ETest/Tests/EventCustomArgsTest.cs index 329af1353344..ad5ffcadde4e 100644 --- a/src/Components/test/E2ETest/Tests/EventCustomArgsTest.cs +++ b/src/Components/test/E2ETest/Tests/EventCustomArgsTest.cs @@ -162,6 +162,14 @@ public void CanAliasBrowserEvent_WithoutAnyNativeListenerForBrowserEvent() Browser.True(() => GetLogLines().Contains("Received custom mouseover event")); } + [Fact] + public void CanRegisterCustomEventAndSupplyIJSObjectReference() + { + Browser.Exists(By.Id("register-sendjsobject")).Click(); + Browser.FindElement(By.Id("trigger-sendjsobject-event-directly")).Click(); + Browser.Equal("Event with IJSObjectReference received: Hello!", () => GetLogLines().Single()); + } + void SendKeysSequentially(IWebElement target, string text) { foreach (var c in text) diff --git a/src/Components/test/testassets/BasicTestApp/EventCustomArgsComponent.razor b/src/Components/test/testassets/BasicTestApp/EventCustomArgsComponent.razor index d79814c7205d..fd6b43d1e5bb 100644 --- a/src/Components/test/testassets/BasicTestApp/EventCustomArgsComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/EventCustomArgsComponent.razor @@ -9,7 +9,8 @@ @ontestevent="@HandleTestEvent" @onkeydown.testvariant="@HandleCustomKeyDown" @onkeydown.yetanother="@HandleYetAnotherKeyboardEvent" - @oncustommouseover="@(e => { LogMessage("Received custom mouseover event"); })"> + @oncustommouseover="@(e => { LogMessage("Received custom mouseover event"); })" + @onsendjsobject="HandleEventWithIJSObjectReference"> Event target
Child @@ -55,6 +56,17 @@ Register custom mouseover event (which has no corresponding native listener) + + + + +