dotnet / MobileBlazorBindings

Experimental Mobile Blazor Bindings - Build native and hybrid mobile apps with Blazor
MIT License
1.2k stars 168 forks source link

NavigationManager does not work anymore on Hybrid Apps #476

Open Lele0037 opened 9 months ago

Lele0037 commented 9 months ago

A year ago (circa) I built an hybrid app using Mobile Blazor Bindings:

dotnet new blazorhybrid -o <my app>

Suddently (maybe due to a recent Google/Android update?) the NavigationManager seems not to be working anymore: my app simply does not navigate to the page it is supposed to go. In another words, the function

@inject NavigationManager navigationManager;

<button @onclick="Navigate">Navigate</button>

@code {
    private void Navigate () {
        navigationManager.NavigateTo("/my-page");
    }
}

does nothing at all. It does not even throw an exception. I noticed, tinkering with the chrome console while the app is running, that when I try to navigate using the javascript function underneath I received the following error:

[chromium] [INFO:CONSOLE(1)] "Uncaught  SecurityError: Failed to execute 'pushState' on 'History': A history state object with URL 'app://0.0.0.0/<my path>' cannot be created in a document with origin 'app://' and URL 'app://0.0.0.0/'.", source:            framework://blazor.desktop.js (1)

Could someone please help me? My app was working perfectly last week and now all the devices where the app is installed are failing one by one. My only guess is that something changed with the default Android Web View app (I noticed it has been updated recently).

Eilon commented 9 months ago

Hi @Lele0037 , I'm not sure what could have caused this, but if you're looking to gain some new features as well as lots of bugs fixes, I recommend using this fork of Mobile Blazor Bindings by @Dreamescaper : https://github.com/Dreamescaper/BlazorBindings.Maui

plamenkraev commented 9 months ago

you can temporarily fix it by overriding navigateTo, by suppressing history recording, you can add it to index.html, something like that

<script>
        let testAnchor;

        var blazorLoading = setInterval(() => {
            if (window.Blazor) {
                clearInterval(blazorLoading);

                Blazor._internal.navigationManager.navigateTo = function (uri, forceLoad, replace) {
                    const absoluteUri = toAbsoluteUri(uri);
                    if (!forceLoad && isWithinBaseUriSpace(absoluteUri)) {
                        // It's an internal URL, so do client-side navigation
                        performInternalNavigation(absoluteUri, false, replace);
                    } else if (forceLoad && location.href === uri) {
                        // Force-loading the same URL you're already on requires special handling to avoid
                        // triggering browser-specific behavior issues.
                        // For details about what this fixes and why, see https://github.com/aspnet/AspNetCore/pull/10839
                        const temporaryUri = uri + '?';
                        location.replace(uri);
                    } else if (replace) {

                    } else {
                        // It's either an external URL, or forceLoad is requested, so do a full page load
                        location.href = uri;
                    }
                }
            }
        }, 5);

        function performInternalNavigation(absoluteInternalHref, interceptedLink, replace = false) {
            DotNet.invokeMethodAsync('Microsoft.MobileBlazorBindings.WebView', 'NotifyLocationChanged', absoluteInternalHref, interceptedLink)
        }

        function isWithinBaseUriSpace(href) {
            const baseUriWithTrailingSlash = toBaseUriWithTrailingSlash(document.baseURI); // TODO: Might baseURI really be null?
            return href.startsWith(baseUriWithTrailingSlash);
        }

        function toBaseUriWithTrailingSlash(baseUri) {
            return baseUri.substr(0, baseUri.lastIndexOf('/') + 1);
        }

        function toAbsoluteUri(relativeUri) {
            testAnchor = testAnchor || document.createElement('a');
            testAnchor.href = relativeUri;
            return testAnchor.href;
        }
    </script>