I'm trying to get the user's city location, but first I want to try coordinates, as I find this hard enough already.
I have this javascript (from another post) but changed the return value;
<script>
window.getCoords = async () => {
const pos = await new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject);
});
return (pos.coords.latitude, pos.coords.longitude);
};
</script>
Assuming, I will get (double latitude, double longitude)
back (correct me if I'm wrong).
Also, I am not sure what the Promise
keyword stands for, I'm assuming It's an old way for async...
After declaring this javascript in my _Host.cshtml
file I go to my razor component.
The component has the following;
@inject IJSRuntime JSRuntime
@using BrowserInterop.Geolocation;
protected override async Task<(double latitude, double longitude)> OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var location = await JSRuntime.InvokeAsync<(double longitude, double lattitude)>("getCoords");
Console.WriteLine("Lat: " + test.lattitude, " Long: " + test.longitude);
}
//If geo-location fails default to IP-based location (this method works fine)
return await GetIpGeolocationAsync();
}
However, once my program runs it crashes once it gets to var location = ...
and I don't get the user location or an error to resolve this matter.
I have searched multiple examples, but all end up the same way. The MS docs also don't give an example on this, any guidance would be appreciated.
I use a service to call my js.
Coordinate.cs
public struct Coordinate
{
public double Latitude { get; set; }
public double Longitude { get; set; }
public double Accuracy { get; set; }
}
geoLocationJsInterop.js
export function getCurrentPosition(dotNetHelper, enableHighAccuracy, maximumAge) {
const options = {
enableHighAccuracy: enableHighAccuracy,
timeout: 5000,
maximumAge: maximumAge
};
function success(position) {
const coordinate = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
accuracy: position.coords.accuracy
};
dotNetHelper.invokeMethodAsync('OnSuccessAsync', coordinate);
}
function error(error) {
const errorDetails = {
errorCode: error.code,
errorMessage: error.message
};
dotNetHelper.invokeMethodAsync('OnErrorAsync', errorDetails);
}
navigator.geolocation.getCurrentPosition(success, error, options);
}
GeoLocationBroker.cs
public class GeoLocationBroker : IGeoLocationBroker
{
private readonly IJSRuntime jsRuntime;
private readonly Lazy<Task<IJSObjectReference>> moduleTask;
private readonly DotNetObjectReference<GeoLocationBroker> dotNetObjectReference;
public GeoLocationBroker(IJSRuntime jsRuntime)
{
this.jsRuntime = jsRuntime;
moduleTask = new(() => this.jsRuntime!.InvokeAsync<IJSObjectReference>(
identifier: "import",
args: "./scripts/geoLocations/geoLocationJsInterop.js")
.AsTask());
dotNetObjectReference = DotNetObjectReference.Create(this);
}
public async ValueTask RequestGeoLocationAsync(bool enableHighAccuracy, int maximumAgeInMilliseconds)
{
var module = await moduleTask.Value;
var dotNetObjectReference = this.dotNetObjectReference;
await module.InvokeVoidAsync(identifier: "getCurrentPosition",
dotNetObjectReference,
enableHighAccuracy,
maximumAgeInMilliseconds);
}
public async ValueTask RequestGeoLocationAsync()
{
await RequestGeoLocationAsync(enableHighAccuracy: true, maximumAgeInMilliseconds: 0);
}
public event Func<Coordinate, ValueTask> CoordinatesChanged = default!;
public event Func<GeolocationPositionError, ValueTask> OnGeolocationPositionError = default!;
[JSInvokable]
public async Task OnSuccessAsync(Coordinate coordinates)
{
await CoordinatesChanged.Invoke(coordinates);
}
[JSInvokable]
public async Task OnErrorAsync(GeolocationPositionError error)
{
await OnGeolocationPositionError.Invoke(error);
}
}
Program.cs
builder.Services.AddScoped<IGeoLocationBroker, GeoLocationBroker>();