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

WebView on iOS using Navigating event fails with obj exception #11544

Open
jjxtra opened this issue Nov 21, 2022 · 14 comments
Open

WebView on iOS using Navigating event fails with obj exception #11544

jjxtra opened this issue Nov 21, 2022 · 14 comments
Labels
area-controls-webview WebView platform/iOS 🍎 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Milestone

Comments

@jjxtra
Copy link

jjxtra commented Nov 21, 2022

Description

I have an anchor tag which when clicked, is supposed to call the navigating event, where I inspect the url and do different things and set cancel to true.

Completion handler passed to -[Microsoft_Maui_Platform_MauiWebViewUIDelegate webView:contextMenuConfigurationForElement:completionHandler:] was not called.

<WebView x:Name="WebBrowser" Navigating="WebBrowser_Navigating">
  <WebView.Source>
    <HtmlWebViewSource>
      <HtmlWebViewSource.Html>
<!-- html snipped for brevity, include a tag with a url in the href and some text -->
      </HtmlWebViewSource.Html>
    </HtmlWebViewSource>
  <WebView.Source>
</WebView>

private void WebBrowser_Navigating(object? sender, WebNavigatingEventArgs e)
{
    e.Cancel = true;
    // business logic here, snipped for brevity
}

Steps to Reproduce

  1. Create new maui app
  2. Add webview component with an html anchor tag in the xaml that points to any url
  3. Hook into the navigating event - Navigating="WebBrowser_Navigating"
  4. Create callback in the xaml.cs file and in the navigating event callback, set e.Cancel to true
  5. Deploy to iOS device
  6. Click the anchor tag in the web view
  7. Crash

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

iOS

Affected platform versions

iOS 13, 14, 15, 16

Did you find any workaround?

No

Relevant log output

Completion handler passed to -[Microsoft_Maui_Platform_MauiWebViewUIDelegate webView:contextMenuConfigurationForElement:completionHandler:] was not called.

Works fine on Windows and Android, no issue.

@jjxtra jjxtra added the t/bug Something isn't working label Nov 21, 2022
@ghost ghost added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label Nov 22, 2022
@jsuarezruiz jsuarezruiz added platform/iOS 🍎 s/needs-repro Attach a solution or code which reproduces the issue and removed legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor labels Nov 22, 2022
@ghost
Copy link

ghost commented Nov 22, 2022

Hi @jjxtra. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md

This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

@Eilon Eilon added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label Nov 22, 2022
@jjxtra
Copy link
Author

jjxtra commented Nov 23, 2022

If it helps, this seams to only happen when building to an iOS device from a Windows machine remotely. Running VS mac, I don't have the issue.

@jjxtra jjxtra closed this as completed Nov 23, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Dec 23, 2022
@Eilon Eilon reopened this Jan 1, 2023
@Eilon
Copy link
Member

Eilon commented Jan 1, 2023

I'm hitting this exact error but I don't have an exact repro yet. In my case I'm deriving from .NET MAUI's WebView in a custom control. I'm overriding a few things here and there but not very much. When I load some custom content into the WebView then on iOS specifically I get that same error after doing some navigations (and then the app crashes and quits).

I'll try to debug more and see what a fix might be.

@ghost ghost added the s/no-recent-activity Issue has had no recent activity label Jan 5, 2023
@ghost ghost closed this as completed Jan 9, 2023
@Eilon Eilon removed s/no-recent-activity Issue has had no recent activity s/needs-repro Attach a solution or code which reproduces the issue labels Jan 9, 2023
@Eilon Eilon reopened this Jan 9, 2023
@dotnet dotnet unlocked this conversation Jan 9, 2023
@anton-yashin
Copy link

This is because MauiWebViewUIDelegate.SetContextMenuConfiguration may not call completionHandler when no webView.Interactions is available. For workaround you should install WKView.UIDelegate where you going to call completion handler. Something like that:

sealed class MauiWebViewUIDelegate2 : MauiWebViewUIDelegate
    {
        public MauiWebViewUIDelegate2(IWebViewHandler handler) : base(handler)
        {
        }

        [SupportedOSPlatform("maccatalyst13.1")]
        [SupportedOSPlatform("ios13.0")]
        [UnsupportedOSPlatform("macos")]
        [UnsupportedOSPlatform("tvos")]
        public override void SetContextMenuConfiguration(WKWebView webView, WKContextMenuElementInfo elementInfo, Action<UIContextMenuConfiguration> completionHandler)
        {
            bool completionHandlerIsInvoked = false;

            base.SetContextMenuConfiguration(webView, elementInfo, cfg =>
            {
                completionHandlerIsInvoked = true;
                completionHandler(cfg);
            });

            if (completionHandlerIsInvoked == false)
                completionHandler(null!);
        }
    }

    sealed class WebViewHandler2 : WebViewHandler
    {
        WKUIDelegate? _delegate;

        public static void MapWKUIDelegate2(IWebViewHandler handler, IWebView webView)
        {
            if (handler is WebViewHandler2 platformHandler)
                handler.PlatformView.UIDelegate = platformHandler._delegate ??= new MauiWebViewUIDelegate2(handler);
        }
    }

    // at your application startup
   WebViewHandler.Mapper.Add(nameof(WKUIDelegate), WebViewHandler2.MapWKUIDelegate2);
   // when maui app is created
  app.ConfigureMauiHandlers(h => h.AddHandler<WebView, WebViewHandler2>());

@jjxtra
Copy link
Author

jjxtra commented Feb 15, 2023

Thanks for the workaround. Obviously it would be ideal not to have to do this kind of hackery. Can someone from Microsoft comment if this is reproduced on your end and if so is there a fix planned for .NET 8, or a patch for .NET 7?

@jsuarezruiz jsuarezruiz added this to the Backlog milestone Mar 2, 2023
@ghost
Copy link

ghost commented Mar 2, 2023

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.

@jmezach
Copy link

jmezach commented Aug 29, 2023

We've probably just hit this issue in our app as well causing seemingly random crashes for some of our users. Unfortunately we can't pinpoint what is causing this exactly, but given the exception we're seeing, the workaround described above and the current implementation here it makes sense. According to the docs it seems you are supposed to call the completionHandler with null if there is nothing to configure. Seems like an easy enough fix so I'd be more than happy to submit a PR if you're willing to take it.

@Sumn3rd
Copy link

Sumn3rd commented Aug 31, 2023

I have unfortunately hit this issue as well. Similar set up and have tried the workaround suggested above however am finding it results in a hang/freeze when trying to return from the browser if external or the default email app for mailto links. Launching and returning from a https:// url works fine if I use the workaround and set the launch mode to:

await Browser.Default.OpenAsync(uri, BrowserLaunchMode.SystemPreferred);

@giloliveira-nmi
Copy link

We're also struggling with this issue, and decided we can't update our app because of it for the time being. Hopefully someone at Microsoft will respond and is willing to take the proposed PR by @jmezach soon!

@edgarssults
Copy link

edgarssults commented Oct 10, 2023

We're seeing the same issue on iOS, but when selecting links by pressing and holding. The link text is selected, but after a second the app crashes without displaying any context menu with this exact exception. Selecting normal text is fine and Android works fine.

Edit:
I just found that setting AllowsLinkPreview to false in my custom web view for iOS (have to implement a custom WebViewHandler) fixes the exception when selecting links. It might fix this case too.

@Zhanglirong-Winnie Zhanglirong-Winnie added s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed labels Oct 19, 2023
@Zhanglirong-Winnie
Copy link

Verified this issue with Visual Studio 17.6.5(build 417). Can repro on iOS platform.

@vindberg
Copy link

vindberg commented Dec 1, 2023

Thanks for the workaround. Obviously it would be ideal not to have to do this kind of hackery. Can someone from Microsoft comment if this is reproduced on your end and if so is there a fix planned for .NET 8, or a patch for .NET 7?

I can confirm this also is an issue in .NET 8.100 final release.

@Hassan14072002
Copy link

This is because MauiWebViewUIDelegate.SetContextMenuConfiguration may not call completionHandler when no webView.Interactions is available. For workaround you should install WKView.UIDelegate where you going to call completion handler. Something like that:

sealed class MauiWebViewUIDelegate2 : MauiWebViewUIDelegate
    {
        public MauiWebViewUIDelegate2(IWebViewHandler handler) : base(handler)
        {
        }

        [SupportedOSPlatform("maccatalyst13.1")]
        [SupportedOSPlatform("ios13.0")]
        [UnsupportedOSPlatform("macos")]
        [UnsupportedOSPlatform("tvos")]
        public override void SetContextMenuConfiguration(WKWebView webView, WKContextMenuElementInfo elementInfo, Action<UIContextMenuConfiguration> completionHandler)
        {
            bool completionHandlerIsInvoked = false;

            base.SetContextMenuConfiguration(webView, elementInfo, cfg =>
            {
                completionHandlerIsInvoked = true;
                completionHandler(cfg);
            });

            if (completionHandlerIsInvoked == false)
                completionHandler(null!);
        }
    }

    sealed class WebViewHandler2 : WebViewHandler
    {
        WKUIDelegate? _delegate;

        public static void MapWKUIDelegate2(IWebViewHandler handler, IWebView webView)
        {
            if (handler is WebViewHandler2 platformHandler)
                handler.PlatformView.UIDelegate = platformHandler._delegate ??= new MauiWebViewUIDelegate2(handler);
        }
    }

    // at your application startup
   WebViewHandler.Mapper.Add(nameof(WKUIDelegate), WebViewHandler2.MapWKUIDelegate2);
   // when maui app is created
  app.ConfigureMauiHandlers(h => h.AddHandler<WebView, WebViewHandler2>());

Hi, is it possible for you to upload a full project showcasing where this needs to be implemented? I'm new to .NET MAUI so could use all the help I can get! Thanks.

@Sumn3rd
Copy link

Sumn3rd commented Apr 10, 2024

@Hassan14072002

Sorry this is late but just incase anyone else needs it:

Firstly add that code to a class possibly down the ios platform directory as it's ios specific.

In mauiprogram.cs add to your CreateMauiApp(); on the var builder add this .ConfigureMauiHandlers

    public static MauiApp CreateMauiApp()
	{
		var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureMauiHandlers((handlers) =>
                        {
#if IOS
                handlers.AddHandler<WebView, WebViewHandler2>();
#endif
                        }).ConfigureFonts.......

Then add to App.cs or wherever you're mapping handlers


Using....
#if IOS
using WebKit;
using Wherever.Your.SealedClassIs (MauiWebViewUIDelegate2) possibly ProjectName.Platforms.iOS
#endif

public App underneath InitializeComponent();

    public App()
    {
             InitializeComponent();
#if IOS

        WebViewHandler.Mapper.Add(nameof(WKUIDelegate), WebViewHandler2.MapWKUIDelegate2);
#endif
}

That will map the handler to the object so on iOS it has said extension.

@Eilon Eilon removed the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-controls-webview WebView platform/iOS 🍎 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Projects
None yet
Development

No branches or pull requests