dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.54k stars 10.05k forks source link

Returning an HTML element from a JS interop call throws an exception. #23369

Open MackinnonBuck opened 4 years ago

MackinnonBuck commented 4 years ago

Describe the bug

When using IJSRuntime.InvokeAsync<ElementReference>(...) to invoke a JS function that returns an HTML element, the following exception is thrown:

Unhandled exception rendering component: An exception occurred executing JS interop: __internalId is required..

This exception happens regardless of whether the HTML element being returned from the JS function is being passed in from .NET as an ElementReference.

To Reproduce

See https://github.com/MackinnonBuck/blazor-element-reference-bug. Build and run the Blazor project, then click the button labeled "Return ElementReference from JS". The full exception is displayed in the browser's console.

Exceptions

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: An exception occurred executing JS interop: __internalId is required.. See InnerException for more details.
Microsoft.JSInterop.JSException: An exception occurred executing JS interop: __internalId is required.. See InnerException for more details. ---> System.Text.Json.JsonException: __internalId is required.
  at Microsoft.AspNetCore.Components.ElementReferenceJsonConverter.Read (System.Text.Json.Utf8JsonReader& reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) <0x2ce5ef0 + 0x000de> in <filename unknown>:0 
  at System.Text.Json.JsonPropertyInfoNotNullable`4[TClass,TDeclaredProperty,TRuntimeProperty,TConverter].OnRead (System.Text.Json.ReadStack& state, System.Text.Json.Utf8JsonReader& reader) <0x2ce5d50 + 0x0003c> in <filename unknown>:0 
  at System.Text.Json.JsonPropertyInfo.Read (System.Text.Json.JsonTokenType tokenType, System.Text.Json.ReadStack& state, System.Text.Json.Utf8JsonReader& reader) <0x2c6fea0 + 0x000c8> in <filename unknown>:0 
  at System.Text.Json.JsonSerializer.HandleValue (System.Text.Json.JsonTokenType tokenType, System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& state) <0x2c6fc00 + 0x000a6> in <filename unknown>:0 
  at System.Text.Json.JsonSerializer.HandleObjectAsValue (System.Text.Json.JsonTokenType tokenType, System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& readStack, System.Text.Json.JsonReaderState& initialState, System.Int64 initialBytesConsumed) <0x2ce5ad0 + 0x000b6> in <filename unknown>:0 
  at System.Text.Json.JsonSerializer.ReadCore (System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& readStack) <0x2c796a8 + 0x00340> in <filename unknown>:0 
  at System.Text.Json.JsonSerializer.ReadValueCore (System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& readStack) <0x2c75cb0 + 0x00584> in <filename unknown>:0 
  at System.Text.Json.JsonSerializer.ReadValueCore (System.Text.Json.Utf8JsonReader& reader, System.Type returnType, System.Text.Json.JsonSerializerOptions options) <0x2c419c0 + 0x0003e> in <filename unknown>:0 
  at System.Text.Json.JsonSerializer.Deserialize (System.Text.Json.Utf8JsonReader& reader, System.Type returnType, System.Text.Json.JsonSerializerOptions options) <0x2c41858 + 0x00024> in <filename unknown>:0 
  at Microsoft.JSInterop.JSRuntime.EndInvokeJS (System.Int64 taskId, System.Boolean succeeded, System.Text.Json.Utf8JsonReader& jsonReader) <0x2cd9d40 + 0x00052> in <filename unknown>:0 
   --- End of inner exception stack trace ---
  at System.Threading.Tasks.ValueTask`1[TResult].get_Result () <0x2cf2f20 + 0x0003c> in <filename unknown>:0 
  at Demo.App.ButtonClicked () [0x00046] in C:\blazor-element-reference-bug\Demo\App.razor:11 
  at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion (System.Threading.Tasks.Task task) <0x2ccd598 + 0x000da> in <filename unknown>:0 
  at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask (System.Threading.Tasks.Task taskToHandle) <0x2cd8278 + 0x000b6> in <filename unknown>:0 
f.printErr @ blazor.webassembly.js:1
f.preRun.push.window.Blazor._internal.dotNetCriticalError @ blazor.webassembly.js:1
_mono_wasm_invoke_js_unmarshalled @ dotnet.3.2.0.js:1
do_icall @ dotnet.wasm:1
do_icall_wrapper @ dotnet.wasm:1
interp_exec_method @ dotnet.wasm:1
interp_runtime_invoke @ dotnet.wasm:1
mono_jit_runtime_invoke @ dotnet.wasm:1
do_runtime_invoke @ dotnet.wasm:1
mono_runtime_try_invoke @ dotnet.wasm:1
mono_runtime_invoke @ dotnet.wasm:1
mono_wasm_invoke_method @ dotnet.wasm:1
Module._mono_wasm_invoke_method @ dotnet.3.2.0.js:1
call_method @ dotnet.3.2.0.js:1
(anonymous) @ dotnet.3.2.0.js:1
endInvokeJSFromDotNet @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
Promise.then (async)
beginInvokeJSFromDotNet @ blazor.webassembly.js:1
_mono_wasm_invoke_js_marshalled @ dotnet.3.2.0.js:1
do_icall @ dotnet.wasm:1
do_icall_wrapper @ dotnet.wasm:1
interp_exec_method @ dotnet.wasm:1
interp_runtime_invoke @ dotnet.wasm:1
mono_jit_runtime_invoke @ dotnet.wasm:1
do_runtime_invoke @ dotnet.wasm:1
mono_runtime_invoke_checked @ dotnet.wasm:1
mono_runtime_try_invoke_array @ dotnet.wasm:1
ves_icall_InternalInvoke @ dotnet.wasm:1
ves_icall_InternalInvoke_raw @ dotnet.wasm:1
do_icall @ dotnet.wasm:1
do_icall_wrapper @ dotnet.wasm:1
interp_exec_method @ dotnet.wasm:1
interp_runtime_invoke @ dotnet.wasm:1
mono_jit_runtime_invoke @ dotnet.wasm:1
do_runtime_invoke @ dotnet.wasm:1
mono_runtime_try_invoke @ dotnet.wasm:1
mono_runtime_invoke @ dotnet.wasm:1
mono_wasm_invoke_method @ dotnet.wasm:1
Module._mono_wasm_invoke_method @ dotnet.3.2.0.js:1
call_method @ dotnet.3.2.0.js:1
(anonymous) @ dotnet.3.2.0.js:1
beginInvokeDotNetFromJS @ blazor.webassembly.js:1
s @ blazor.webassembly.js:1
e.invokeMethodAsync @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
t.dispatchEvent @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
(anonymous) @ blazor.webassembly.js:1
e.onGlobalEvent @ blazor.webassembly.js:1

Further technical details

Blazor WebAssembly project (.NET standard 2.1)

Output of dotnet --info:

.NET SDK (reflecting any global.json):
 Version:   5.0.100-preview.6.20318.15
 Commit:    4356580024

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19041
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\5.0.100-preview.6.20318.15\

Host (useful for support):
  Version: 5.0.0-preview.6.20305.6
  Commit:  4ba9ecaabd

.NET SDKs installed:
  3.1.301 [C:\Program Files\dotnet\sdk]
  5.0.100-preview.6.20318.15 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.0-preview.6.20312.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.0-preview.6.20305.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.0-preview.6.20308.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download

IDE: Visual Studio Enterprise 2019

marinasundstrom commented 4 years ago

Is there a workaround?

marinasundstrom commented 3 years ago

Related: https://github.com/dotnet/aspnetcore/issues/26496

marinasundstrom commented 3 years ago

Just to make it clear: As I get it: ElementReference is a platform-independent Blazor concept, not a JS concept. So you should use IJSObjectReference when passing JavaScript references that do not map to what Blazor keeps track of as part of its render tree.

Issues arise when using older libraries that are using ElementReference but not IJSObjectReference which is quite new.

Community-provided BlazorCanvas, for example. Images to be drawn required to be passed as ElementReference which does not allow for dynamic loading in JavaScript - since you cannot and should not return an ElementReference from JavaScript. The reason is that it is not being tracked by Blazor and does not have an id,

However, you can pass an ElementReferenceto JavaScript since it then represents an actual element rendered by Blazor.

TanayParikh commented 3 years ago

Related to https://github.com/dotnet/aspnetcore/issues/26049?

ghost commented 3 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

ghost commented 2 years ago

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

ghost commented 1 year ago

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

ghost commented 1 year ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.