Aspire NET 9 Blazor Project: InteractiveAuto Globally
17:19 04 Nov 2025

I have a question with a setup of one of my components that relies heavily on JSInterop. The component contains a Google map and all of my data for initializing and displaying data on that map needs something from JSInterop. I was loading the data in a model inside OnInitializedAsync like I would normally do and then doing all of my JSInterop inside OnAfterRenderAsync. This worked fine with InteractiveAuto but when I refresh the browser and turn to WebAssembly, JSInterop wasn't ready yet so my data comes back as null. I moved all of the database calls to OnAfterRenderAsync during the first run (pre-render) and I'm basically only starting SignalR in OnInitializedAsyn.

Is this a good approach? Should I load my data from my database inside OnAfterRenderAsync during the first run (pre-render)?

Below is my new setup:

protected async override Task OnAfterRenderAsync(bool firstRender)
{
    if (!firstRender)
    {
        return;
    }    

    try
    {
        TimeZoneModule = await JSRuntime.InvokeAsync("import", Cts.Token, "./timezone.js");

        string timeZone = "Eastern Standard Time";

        if (TimeZoneModule is not null)
        {
            var tzId = await TimeZoneModule.InvokeAsync(
                "getBrowserTimeZone", Cts.Token);

            TimeZoneInfo.TryConvertIanaIdToWindowsId(tzId, out var windowsTzId);
            if (!string.IsNullOrEmpty(windowsTzId))
            {
                timeZone = windowsTzId;
            }
        }
        var dotNetRef = DotNetObjectReference.Create(this);
        MapModule = await JSRuntime.InvokeAsync("import", Cts.Token, "./map-module.js");
        await MapModule.InvokeVoidAsync("setMapDotNetReference", Cts.Token, dotNetRef);
        MapInstance = await MapModule.InvokeAsync("initMap", Cts.Token, MapElement);
        await MapModule.InvokeVoidAsync("setInfoWindow", Cts.Token);
        await MapModule.InvokeVoidAsync("setMapEvents", Cts.Token);

        ViewModel = await MapService.InitializeMap(User.DefaultBusinessId, timeZone, Cts.Token);
        MapInitialized = true;
        await ApplyMapSettingsAsync();
        
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Map initialization failed: {ex.Message}");
    }    
}

protected override async Task OnInitializedAsync()
{   

    await InitializeSignalRAsync();  

}

private async Task ApplyMapSettingsAsync()
{
    if (!MapInitialized || MapModule is null || MapInstance is null || ViewModel is null)
    {
        return;
    }

    if (ViewModel.BusinessMapSetting is not null)
    {
        await MapModule.InvokeVoidAsync("setOptions", Cts.Token, ViewModel.BusinessMapSetting);
    }

    if (ViewModel.Vehicles is not null)
    {
        await MapModule.InvokeVoidAsync("addTruckMarkers", Cts.Token, null, ViewModel.Vehicles);
    }

    if (ViewModel.Plants is not null)
    {
        await MapModule.InvokeVoidAsync("addPlantMarkers", Cts.Token, ViewModel.Plants);
    }
}
blazor .net-9.0 dotnet-aspire