Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in ContextMenuTrigger AfterRenderAsync on iOS #80

Closed
buist-sharris opened this issue Aug 24, 2020 · 15 comments
Closed

Error in ContextMenuTrigger AfterRenderAsync on iOS #80

buist-sharris opened this issue Aug 24, 2020 · 15 comments

Comments

@buist-sharris
Copy link

buist-sharris commented Aug 24, 2020

We have been experiencing an issue on a page that uses Blazor Context Menu. If a user opens the page on linked Apple Devices (i.e. an iPad) and then opens the same page on an iPhone, the app crashes. It seems it could be related to "handoff" somehow, be we aren't entirely certain. After enabling detailed errors and hooking a phone up to a mac to gain access to a Safari developer console, we were able to see the actual error that was occurring....

Error: Microsoft.JSInterop.JSException: null is not an object (evaluating 'e.dataset')
_content/Blazor.ContextMenu/blazorContextMenu.min.js:1:3553
[native code]
_framework/Blazor.ContextMenu/blazor.server.js:8:31426
Promise@[native code]
beginInvokeJSFromDotNet@_framework/Blazor.ContextMenu/blazor.server.js:8:31401
forEach@[native code]
_framework/Blazor.ContextMenu/blazor.server.js:1:19180
_framework/Blazor.ContextMenu/blazor.server.js:1:17183
_framework/Blazor.ContextMenu/blazor.server.js:1:38100
at Microsoft.JSInterop.JSRuntime.InvokeWithDefaultCancellation[T](String identifier, Object[] args)
at BlazorContextMenu.ContextMenuTrigger.OnAfterRenderAsync(Boolean firstRender)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

Error: Circuit has been shut down due to error.

After I remove the Context Menu from the page, the error is unable to be reproduced.

It's obviously a bit of a perfect storm and very difficult to provide a reproduction as it only seems to happen after opening the page on multiple iOS devices and then only on the phone. I'm hoping maybe the error itself may provide a clue as to what's going on or a potential fix?

@stavroskasidis
Copy link
Owner

This seems really weird. I don't have any iOS devices and I have not used this "Handoff" feature.

Could you please reference the unminified "_content/Blazor.ContextMenu/blazorContextMenu.js" in your code instead of the minified version and post the error again?

Maybe I can guess why the error is happening if I can see where it throws on the unminified code.

Also is the error occuring when opening a context menu or just by loading the page?

@buist-sharris
Copy link
Author

Thanks for the quick reply! I will indeed switch to the unminified script file and see what we can get. It is definitely a very bizarre set of circumstances that seem to be causing it. It takes a bit of work to reproduce and capture the error and we only have one Mac in the organization, so I'll have a co-worker do this tomorrow.

As far as your other question, it crashes the app simply by loading the page. However, as indicated, it doesn't "break" until you open the same page on another Apple device, then it breaks for phones only. Once it's "broken" too, it's broken. The context menu is on the detail lines of a grid. The only way to "fix" the broken page for a phone is to delete all the lines from the grid.

@buist-sharris
Copy link
Author

OK, we were able to reproduce the error again, this time using the unminified script.

Error: Microsoft.JSInterop.JSException: null is not an object (evaluating 'triggerElement.dataset')
_content/Blazor.ContextMenu/blazorContextMenu.js:264:23
[native code]
_framework/Blazor.ContextMenu/blazor.server.js:8:31426
Promise@[native code]
beginInvokeJSFromDotNet@_framework/Blazor.ContextMenu/blazor.server.js:8:31401
forEach@[native code]
_framework/Blazor.ContextMenu/blazor.server.js:1:19180
_framework/Blazor.ContextMenu/blazor.server.js:1:17183
_framework/Blazor.ContextMenu/blazor.server.js:1:38100
at Microsoft.JSInterop.JSRuntime.InvokeWithDefaultCancellation[T](String identifier, Object[] args)
at BlazorContextMenu.ContextMenuTrigger.OnAfterRenderAsync(Boolean firstRender)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

@stavroskasidis
Copy link
Owner

The triggerElement was not captured correctly by the blazor framework to be passed down to javascript.

This is really really weird. I am starting to think that this is a blazor server side issue, because there is no way that the triggerElement would be null at that point. Something is probably getting blazor confused on what is rendered etc. I deduce
that maybe because of "Handoff", the circuit is the same and blazor server does not work properly.

I think further investigation is required, probably something that we have to reproduce for the blazor team.

Can you please try to reproduce by creating 2 new projects, one blazor server and one in blazor wasm and then do the following

  1. Change "Index.razor" to this
@inject IJSRuntime jsRuntime
@page "/"

<h1 @ref="h1" data-value="some data">Hello, world!</h1>

@if(data != null)
{
    <p>Data from interop: @data</p>
}

@code{
    ElementReference h1;
    string data;
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            data = await jsRuntime.InvokeAsync<string>("GetData", h1);
            Console.WriteLine($"Read data from element: {data}");
            StateHasChanged();
        }
    }
}
  1. Add the following script in your _Host.razor (blazor server) or index.html (blazor wasm).
<script>
        GetData = function (element) {
            return element.dataset["value"];
        }
</script>
  1. Run the app, see that the message "Data from interop: some data" appears beneath "Hello, world!"
  2. Use the "Handoff" thing and see how it behaves on the phones.

@buist-sharris
Copy link
Author

We've created the requested projects and there does not appear to be any errors (i.e. we're unable to "break" it) after opening it on a phone, then a different device, then the phone again. In all cases, the page renders and correctly displays the "Data from interop: some data".

@Webreaper
Copy link

I'm seeing the same issue - running a Blazor server app on Linux, and accessing it via MacOS, so I'm interested to know what the resolution might be.

@Webreaper
Copy link

Did you ever get to the bottom of this?

@stavroskasidis
Copy link
Owner

No sorry. I just don't have the means to reproduce it. Maybe cloning the repo and adding the contextmenu as a project reference instead of a nuget package will help use locate the problem

@MichelJansson
Copy link

MichelJansson commented Oct 9, 2021

Hi, thanks for a cool package! I'm having a similar issue in a wasm project, using .NET6, and BlazorContextMenu 1.10.0 in both Chrome/Windows and Safari/iOS.

It always happen at a very specific point in time, and can only be replicated at that time. I use it for a user-menu, meaning it's only available for signed in users. I'm using built-in asp.net identity, and the menu resides within a AuthorizeView (see code below). In this exact setup, the error always comes directly after successful login, but never again until logout/login.

The issue goes away if I place the ContextMenu outside the AuthorizeView, but then I don't have clean access to the authentication state inside the menu.

Error

Microsoft.JSInterop.JSException: Cannot read properties of null (reading 'dataset')
TypeError: Cannot read properties of null (reading 'dataset')
    at Object.f.RegisterTriggerReference (https://localhost:5001/_content/Blazor.ContextMenu/blazorContextMenu.min.js:1:3886)
    at https://localhost:5001/_framework/blazor.webassembly.js:1:3332
    at new Promise (<anonymous>)
    at Object.beginInvokeJSFromDotNet (https://localhost:5001/_framework/blazor.webassembly.js:1:3306)
    at Object.At [as invokeJSFromDotNet] (https://localhost:5001/_framework/blazor.webassembly.js:1:58527)
    at _mono_wasm_invoke_js_blazor (https://localhost:5001/_framework/dotnet.6.0.0-rc.2.21470.23.nm4vlkk3nn.js:1:193753)
    at wasm://wasm/009459e2:wasm-function[2590]:0x80584
    at wasm://wasm/009459e2:wasm-function[2310]:0x68b2b
    at wasm://wasm/009459e2:wasm-function[7016]:0x17babb
    at wasm://wasm/009459e2:wasm-function[6831]:0x172bbc
   at Microsoft.JSInterop.JSRuntime.<InvokeAsync>d__16`1[[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at BlazorContextMenu.ContextMenuTrigger.OnAfterRenderAsync(Boolean firstRender)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

Debug

image

Code

<AuthorizeView Context="authContext">
    <Authorized>
        <ContextMenu Id="userMenu" Animation="Animation.FadeIn">
            <Item>@authContext?.User?.Identity?.Name</Item>
            <Seperator />
            <Item OnClick="BeginSignOut">@Loc["Log out"]</Item>
        </ContextMenu>

        <ContextMenuTrigger MenuId="userMenu" MouseButtonTrigger="MouseButtonTrigger.Both">
            <button class="btn btn-avatar">
                <i class="bi bi-person-circle text-secondary"></i>
            </button>
        </ContextMenuTrigger>

    </Authorized>
    <NotAuthorized>
        ...
    </NotAuthorized>
</AuthorizeView>

@stavroskasidis
Copy link
Owner

Thank you for the reproduction steps.
I am gonna investigate this asap and come up with a fix.

Blazor in .net 6 supports some new was to initialize startup code so that might help but I will have to refactor the JS part of the lib to a module for that to work.

stavroskasidis added a commit that referenced this issue Oct 11, 2021
Added some guards attempting to fix #80
@Webreaper
Copy link

Is it fixed? Nice!! Great demonstration of how a decent repro makes a fix easy. Thanks to @MichelJansson for creating it.

@stavroskasidis
Copy link
Owner

stavroskasidis commented Oct 11, 2021

Can you please use version 1.10.1 to see if it is fixed for you ?
I was partially able to reproduce but not consistently.

@Webreaper
Copy link

I removed BlazorContextMenu and replaced it with Radzen temporarily until this issue was fixed; I'll have to add your project back into mine and test it, so it won't be something I can do for a couple of days.

@MichelJansson
Copy link

That was fast - thanks!

Can you please use version 1.10.1 to see if it is fixed for you ? I was partially able to reproduce but not consistently.

After a quick test, it seems to work, no more exception! I'll test it more thoroughly later this week.

@stavroskasidis
Copy link
Owner

Nice, I will close this issue then. Please reopen it if you find some problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants