-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Description
Is there an existing issue for this?
- I have searched the existing issues
Description
Hi there,
when supporting multiple timezones, the initalization of the abp application of Maui Blazor Apps fails.
This is the exception thrown:
An error occurred during the initialize Volo.Abp.Modularity.OnApplicationInitializationModuleLifecycleContributor phase of the module Volo.Abp.AspNetCore.Components.MauiBlazor.AbpAspNetCoreComponentsMauiBlazorModule, Volo.Abp.AspNetCore.Components.MauiBlazor, Version=9.3.5.0, Culture=neutral, PublicKeyToken=null: Cannot invoke JavaScript outside of a WebView context.. See the inner exception for details."
Inner exception message:
"Cannot invoke JavaScript outside of a WebView context."
After some debugging I found out that the MauiBlazorCachedApplicationConfigurationClient fails while initalizing because the js runtime is invoked when multiple time zones are supported by clock. See starting from here:
Line 81 in ef9fcde
| if (Clock.SupportsMultipleTimezone) |
Reproduction Steps
- Create a new abp solution using Maui Blazor as UI Framework.
- Support multible timezones.
- Start the maui blazor app.
Expected behavior
The Application should start and initalize the timezone properly, instead of failing to start.
Actual behavior
See above. Pasted stack trace there.
Regression?
I dont know.
Known Workarounds
Quirky Workaround:
Create a cached application configuration client, that overrides the `InitializeAsync``-Method and remove invokes to the jsruntime. Put the timezome initalization in some actual component, that can use the JSRuntime.
Here is an example what I did:
[Volo.Abp.DependencyInjection.Dependency(ReplaceServices = true)]
[ExposeServices(typeof(ICachedApplicationConfigurationClient), typeof(MauiBlazorCachedApplicationConfigurationClient))]
public class MyMauiBlazorCachedApplicationConfigurationClient(
AbpApplicationConfigurationClientProxy applicationConfigurationClientProxy,
ApplicationConfigurationCache cache,
ICurrentTenantAccessor currentTenantAccessor,
ICurrentTimezoneProvider currentTimezoneProvider,
AuthenticationStateProvider authenticationStateProvider,
AbpApplicationLocalizationClientProxy applicationLocalizationClientProxy,
ApplicationConfigurationChangedService applicationConfigurationChangedService,
IJSRuntime jsRuntime,
IClock clock
) : MauiBlazorCachedApplicationConfigurationClient(applicationConfigurationClientProxy, cache, currentTenantAccessor, currentTimezoneProvider, authenticationStateProvider, applicationLocalizationClientProxy, applicationConfigurationChangedService, jsRuntime, clock)
{
public override async Task InitializeAsync()
{
var configurationDto = await ApplicationConfigurationClientProxy.GetAsync(
new ApplicationConfigurationRequestOptions
{
IncludeLocalizationResources = false
}
);
var localizationDto = await ApplicationLocalizationClientProxy.GetAsync(
new ApplicationLocalizationRequestDto
{
CultureName = configurationDto.Localization.CurrentCulture.Name,
OnlyDynamics = true
}
);
configurationDto.Localization.Resources = localizationDto.Resources;
Cache.Set(configurationDto);
CurrentTenantAccessor.Current = new BasicTenantInfo(
configurationDto.CurrentTenant.Id,
configurationDto.CurrentTenant.Name);
ApplicationConfigurationChangedService.NotifyChanged();
}
}Added this to the initalization of our footer component (I know quirky but sufficient for a quick fix):
[Inject]
protected ICachedApplicationConfigurationClient ApplicationConfigurationClient { get; set; } = default!;
[Inject]
protected IJSRuntime JSRuntime { get; set; } = default!;
[Inject]
protected IClock Clock { get; set; } = default!;
[Inject]
protected ICurrentTimezoneProvider CurrentTimezoneProvider { get; set; } = default!;
private static bool _isTimezoneInitialized;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
await InitalizeTimeZone();
}
private async Task InitalizeTimeZone()
{
if (!Clock.SupportsMultipleTimezone || _isTimezoneInitialized)
{
return;
}
var configuration = await ApplicationConfigurationClient.GetAsync();
try
{
CurrentTimezoneProvider.TimeZone = !configuration.Timing.TimeZone.Iana.TimeZoneName.IsNullOrWhiteSpace()
? configuration.Timing.TimeZone.Iana.TimeZoneName
: await JSRuntime.InvokeAsync<string>("abp.clock.getBrowserTimeZone");
await JSRuntime.InvokeAsync<string>("abp.clock.setBrowserTimeZoneToCookie");
_isTimezoneInitialized = true;
}
catch
{
//ignore
}
}Version
9.3.5
User Interface
Blazor
Database Provider
EF Core (Default)
Tiered or separate authentication server
Tiered
Operation System
Windows (Default)
Other information
No response