geolocationblazor-server-sidejavascript-interop

Get GeoLocation in Blazor Server .NET 8


New to Blazor, so apologies if this is just bad code, but I am having issues with getting Javascript Interop to work here. I am attempting to get the user to allow GeoLocation from a button onSubmit. I am not receiving any errors, but I'm also not getting the JSInvokable methods to fire.

My Blazor page:

 @using Microsoft.AspNetCore.Components.Forms
 @inject IJSRuntime JsRuntime

<EditForm EditContext="editContext" FormName="MessageForm" OnValidSubmit="@GetLoc">
     <button class="btn btn-primary" data-callback="onSubmit" data-action="GetLocation">Share Your Location to Load</button>
</EditForm>

@code
{
    private DotNetObjectReference<Dealer>? dotNet;
    private double geoLat, geoLong;

    private async Task GetLoc()
    {
        try
        {
            dotNet = DotNetObjectReference.Create(this);
            var result = await JsRuntime.InvokeAsync<object>("blazorGetLocation", dotNet);
        }
        catch (Exception ex)
        {
            // Handle exceptions
        }
    }

    [JSInvokable]
    public void ReturnLocation(double latitude, double longitude)
    {
        geoLat = latitude;
        geoLong = longitude;
    }

    [JSInvokable]
    public void ReturnError(string errorMessage)
    {
        geoLat = 0;
        geoLong = 0;
    }

    private EditContext? editContext;

    [SupplyParameterFromForm]
    public GeoLocation? geoLoc { get; set; }

    protected override async Task OnInitializedAsync()
    {
        geoLoc ??= new();
        editContext = new(geoLoc);
    }
}

My Javascript:

window.returnLocation = function (dotNet) {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function (position) {
            dotNet.invokeMethodAsync('ReturnLocation', position.coords.latitude, position.coords.longitude);
        });
    } else {
        dotNet.invokeMethodAsync('ReturnError', 'Some error text.');
    }
};

Solution

  • After reading (and re-reading) everything I could find on this, the issue came from where I was trying to call JsRuntime.InvokeAsync method.

    By using @rendermode InteractiveServer and calling "var result = await JsRuntime.InvokeAsync("blazorGetLocation", dotNet)" from within the OnAfterRenderAsync override, the code works fine now.