Geolocation
Geolocation is a component that reads the position of the user's device from the browser's Geolocation API. It can:
- request the current position once, and return it to your server code;
- watch the position and fire an event every time the device moves.
The browser works out the position from GPS, Wi-Fi, cell towers or the IP address, depending on the device. The result says how accurate it is.
Installation
Add the Wisej-4-Geolocation package to your Wisej.NET project:
dotnet add package Wisej-4-Geolocation
The package targets .NET Framework 4.8 and .NET 8 or later (including the -windows, Android, iOS and Mac Catalyst targets). After a rebuild, Geolocation appears in the Visual Studio toolbox. It's a component, so dropping it on a page puts it in the component tray.
Browsers expose the position only to pages served from a secure context: HTTPS, or http://localhost during development. The first request makes the browser ask the user for permission. If the user refuses, or the page isn't secure, you get a position with Status = PermissionDenied, not an exception. Always check Status before using the coordinates.
Getting the current position
GetCurrentPositionAsync() asks the browser for the position and returns a Position. The task doesn't fault on failure: the error is in Status and ErrorMessage.
- C#
- VB.NET
using Wisej.Ext.Geolocation;
private async void buttonLocate_Click(object sender, EventArgs e)
{
var position = await this.geolocation1.GetCurrentPositionAsync();
if (position.Status == StatusCode.Success)
this.labelPosition.Text = $"{position.Latitude:F5}, {position.Longitude:F5} (±{position.Accuracy:F0} m)";
else
AlertBox.Show("Location unavailable: " + position.Status, MessageBoxIcon.Warning);
}
Imports Wisej.Ext.Geolocation
Private Async Sub ButtonLocate_Click(sender As Object, e As EventArgs) Handles ButtonLocate.Click
Dim position = Await Me.Geolocation1.GetCurrentPositionAsync()
If position.Status = StatusCode.Success Then
Me.LabelPosition.Text = $"{position.Latitude:F5}, {position.Longitude:F5} (±{position.Accuracy:F0} m)"
Else
AlertBox.Show("Location unavailable: " & position.Status.ToString(), MessageBoxIcon.Warning)
End If
End Sub
GetCurrentPosition(callback) does the same with a callback, for code that can't be async.
To answer quickly, GetCurrentPosition and GetCurrentPositionAsync accept a position the browser has cached, however old it is. The MaximumAge property doesn't apply to them. When you need a fresh fix, check TimeStamp on the result, or use ActiveWatch, which honors MaximumAge.
Watching the position
Set ActiveWatch to true, and the browser reports every change of position. Each report updates LastPosition and fires PositionChanged. Errors are reported the same way, with the error in LastPosition.Status.
- C#
- VB.NET
private void Page1_Load(object sender, EventArgs e)
{
this.geolocation1.EnableHighAccuracy = true;
this.geolocation1.MaximumAge = 10000; // accept positions up to 10 s old
this.geolocation1.ActiveWatch = true;
}
private void geolocation1_PositionChanged(object sender, EventArgs e)
{
var position = this.geolocation1.LastPosition;
if (position.Status == StatusCode.Success)
this.googleMap1.AddMarker("me", position.Latitude, position.Longitude, center: true);
}
Private Sub Page1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Geolocation1.EnableHighAccuracy = True
Me.Geolocation1.MaximumAge = 10000 ' accept positions up to 10 s old
Me.Geolocation1.ActiveWatch = True
End Sub
Private Sub Geolocation1_PositionChanged(sender As Object, e As EventArgs) Handles Geolocation1.PositionChanged
Dim position = Me.Geolocation1.LastPosition
If position.Status = StatusCode.Success Then
Me.GoogleMap1.AddMarker("me", position.Latitude, position.Longitude, center:=True)
End If
End Sub
The example shows the position on a GoogleMaps control. Set ActiveWatch = false to stop watching.
With EnableHighAccuracy, a phone keeps its GPS on while the watch is active, and each report is a round trip to the server. Turn ActiveWatch on only while a page needs live tracking, and turn it off when the user leaves that page.
Properties
| Property | Default | What it does |
|---|---|---|
EnableHighAccuracy | false | Asks for the most accurate position the device can give, typically GPS on phones. It's slower and uses more power. |
Timeout | -1 | How long, in milliseconds, the device may take to return a position before the request fails with Timeout. -1 means no limit. |
MaximumAge | -1 | For the active watch only: the maximum age, in milliseconds, of a cached position that's still acceptable. 0 forces a fresh fix, and -1 accepts any cached position. |
ActiveWatch | false | Watches the position and fires PositionChanged on every change. |
LastPosition | none | The last position reported by the active watch. |
With the default Timeout of -1, a device that can't get a fix (indoors with GPS only, or with location services turned off) may never answer, and your await never completes. Set a timeout, such as 15000 for 15 seconds, so that you always get a result.
The position
A Position has:
| Property | Meaning |
|---|---|
Status | A StatusCode: Success, PermissionDenied, PositionUnavailable, Timeout or InvalidResponse. |
ErrorMessage | The browser's error message, or null. |
Latitude, Longitude | The position, in decimal degrees. |
Accuracy | The radius of uncertainty of the latitude and longitude, in meters. |
Altitude, AltitudeAccuracy | Meters above sea level and their accuracy. NaN when the device doesn't provide them, which is common on desktops. |
Heading, Speed | The direction of travel in degrees clockwise from true north, and the speed in m/s. NaN when not available. |
TimeStamp | When the position was taken, in UTC. |
ToString() returns a one-line summary for logging.
On a desktop, the position usually comes from Wi-Fi or the IP address and can be off by hundreds of meters, or more. Show Accuracy to the user, or ignore positions whose accuracy is worse than your feature needs.
Events
| Event | When |
|---|---|
PositionChanged | While ActiveWatch is true, the device reports a new position or an error. Read it from LastPosition. |
API reference
GeolocationPositionStatusCode- The whole
Wisej.Ext.Geolocationnamespace