dotnet / MobileBlazorBindings

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

Hybrid Windows crash when using IJSRuntime early on page load #259

Open Kukks opened 3 years ago

Kukks commented 3 years ago

Version: 0.6.18-preview Platform: Windows WPF Exception:

System.InvalidOperationException: AttachToIpcChannel must be called before using IJSRuntime.
   at Microsoft.MobileBlazorBindings.WebView.BlazorHybridJSRuntime.ThrowIfIpcNotSet()
   at Microsoft.MobileBlazorBindings.WebView.BlazorHybridJSRuntime.BeginInvokeJS(Int64 asyncHandle, String identifier, String argsJson)
   at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](String identifier, CancellationToken cancellationToken, Object[] args)
   at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](String identifier, Object[] args)
   at Microsoft.JSInterop.JSRuntimeExtensions.InvokeAsync[TValue](IJSRuntime jsRuntime, String identifier, Object[] args)
   at Hara.WebCommon.JsInteropConfigProvider.GetRaw(String key) in C:\Git\Hara\Hara.WebCommon\JsInteropConfigProvider.cs:line 31

Cause: When loading a component inside hybrid blazor app inside MBB Windows, that uses IJSRuntime (in my case it is a call to localstorage.get), nested under OnAfterRenderAsync(firstRender) where firstRender is true.

Source: https://github.com/Kukks/Hara/tree/bump-and-fix-windows-support

jspuij commented 3 years ago

The most logical reason would be that you inject IJSRuntime in a class that is registered as Singleton. IJSRuntime is registered as scoped because it is setup and torn down between page(reloads) en while navigating away etc. You cannot inject it into a singleton. Change the registration from Singleton to scoped and it should work. Also think about the fact that Blazor can be unloaded and reloaded on demand (e.g. during screen rotation, when the app is put into the background, or when navigating away to an external link. So make sure that all tear-down and setup happens nicely and that you persist state (if you have to), because you cannot be sure that Blazor keeps running.

arivera12 commented 3 years ago

@Kukks I ran exactly into this error. I fix it using xamarin essentials secure storage instead of browser storage when working with native devices. I did a common interface which manage platform storage.

husam-ebish commented 3 years ago

@Kukks I ran exactly into this error. I fix it using xamarin essentials secure storage instead of browser storage when working with native devices. I did a common interface which manage platform storage.

Thank you for the idea :) it works fine on Android by following this instructions . On the windows application, I got this exception:

System.AggregateException: 'One or more errors occurred. (This functionality is not implemented in the portable version of this assembly. You should reference the NuGet package from your main application project in order to reference the platform-specific implementation.)'.

This exception was originally thrown at this call stack:
    Xamarin.Essentials.SecureStorage.PlatformGetAsync(string)
    Xamarin.Essentials.SecureStorage.GetAsync(string)
    MyApplication.App.MyTask() in App.cs

How can I store on secure storage from the windows application? Thank you in advance

jspuij commented 3 years ago

@husam-ebish, use MBB's own ProtectedStorage:

https://github.com/dotnet/MobileBlazorBindings/tree/main/src/Microsoft.MobileBlazorBindings.ProtectedStorage

arivera12 commented 3 years ago

@Kukks I ran exactly into this error. I fix it using xamarin essentials secure storage instead of browser storage when working with native devices. I did a common interface which manage platform storage.

Thank you for the idea :) it works fine on Android by following this instructions . On the windows application, I got this exception:

System.AggregateException: 'One or more errors occurred. (This functionality is not implemented in the portable version of this assembly. You should reference the NuGet package from your main application project in order to reference the platform-specific implementation.)'.

This exception was originally thrown at this call stack:
    Xamarin.Essentials.SecureStorage.PlatformGetAsync(string)
    Xamarin.Essentials.SecureStorage.GetAsync(string)
    MyApplication.App.MyTask() in App.cs

How can I store on secure storage from the windows application? Thank you in advance

Xamarin essentials is not supported on win32/wpf but a port is being developed

Take a look of this PR

https://github.com/xamarin/Essentials/pull/1079