BlazorBasics.Maps.Services 1.3.2

dotnet add package BlazorBasics.Maps.Services --version 1.3.2
                    
NuGet\Install-Package BlazorBasics.Maps.Services -Version 1.3.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BlazorBasics.Maps.Services" Version="1.3.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BlazorBasics.Maps.Services" Version="1.3.2" />
                    
Directory.Packages.props
<PackageReference Include="BlazorBasics.Maps.Services" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add BlazorBasics.Maps.Services --version 1.3.2
                    
#r "nuget: BlazorBasics.Maps.Services, 1.3.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package BlazorBasics.Maps.Services@1.3.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=BlazorBasics.Maps.Services&version=1.3.2
                    
Install as a Cake Addin
#tool nuget:?package=BlazorBasics.Maps.Services&version=1.3.2
                    
Install as a Cake Tool

Nuget Nuget

Geolocation Service for Blazor

A lightweight and efficient Blazor service for interacting with the Browser's Geolocation API. This service uses JS Interop with Lazy Loading to ensure that JavaScript resources are only loaded when needed.

Features

  • Always answers: every request carries a timeout on the JavaScript side and another on the .NET side, so a browser that never calls back ends as a failed reading and not as a call that hangs.
  • Low accuracy fallback: when a high accuracy request times out or the fix never arrives, a coarse network position is requested instead. A gps fix indoors is a fix that does not arrive.
  • A reason for every failure: IExtendedGeolocationService says whether it was the permission, an unavailable position, a timeout, a browser without the api or a page that is not a secure context.
  • Lazy Initialization: The JavaScript module is loaded only upon the first method call, and a load that failed is retried instead of being remembered as a permanent failure.
  • Memory Management: Implements IAsyncDisposable to properly release JavaScript object references.

Registration

Add the service to your Dependency Injection (DI) container in Program.cs:

builder.Services.AddGeoService();

The defaults can be changed once for the whole application:

builder.Services.AddGeoService(options =>
{
    options.EnableHighAccuracy = true;
    options.TimeoutMilliseconds = 15000;
    options.MaximumAgeMilliseconds = 0;
    options.FallbackToLowAccuracy = true;
    options.LowAccuracyTimeoutMilliseconds = 10000;
    options.LowAccuracyMaximumAgeMilliseconds = 60000;
});

Usage

Inject IExtendedGeolocationService to get the coordinates and, when there are none, the reason why.

@page "/location"
@inject IExtendedGeolocationService GeolocationService

<PageTitle>Location Tracker</PageTitle>

<h1>Geolocation</h1>

@if (Reading?.IsSuccess == true)
{
    <p>Latitude: @Reading.Position.Latitude</p>
    <p>Longitude: @Reading.Position.Longitude</p>
    <p>Accuracy: @Reading.AccuracyInMeters m</p>
}
else if (Reading is not null)
{
    <p>@Message</p>
}

<button class="btn btn-primary" @onclick="GetUserLocation" disabled="@IsLocating">
    Get My Location
</button>

@code {
    GeolocationReading Reading;
    string Message;
    bool IsLocating;

    async Task GetUserLocation()
    {
        IsLocating = true;
        Reading = await GeolocationService.ReadPositionAsync();
        IsLocating = false;

        Message = Reading.FailureReason switch
        {
            GeolocationFailureReason.None => null,
            GeolocationFailureReason.PermissionDenied => "Allow this site to use your location and try again.",
            GeolocationFailureReason.PositionUnavailable => "Turn on the location services of your device and try again.",
            GeolocationFailureReason.Timeout => "Your device could not find your position. Move somewhere with a clearer sky and try again.",
            GeolocationFailureReason.InsecureContext => "This page has to be served over https to read your location.",
            GeolocationFailureReason.NotSupported => "This browser cannot read your location.",
            _ => "We could not read your location. Try again."
        };
    }
}

Do not gate the request behind the permission check. Before the user has answered once, the state is Prompt and not Granted, so asking first is how an application ends up never showing the browser prompt at all. Request the position, and read the permission afterwards only to tell a denial apart from a device that could not find itself.

API Reference

IExtendedGeolocationService

Method Type Description
ReadPositionAsync(options, cancellationToken) ValueTask<GeolocationReading> Requests the position and returns it, or the reason why there is none. Never throws for a browser side failure.
ReadPermissionStateAsync(cancellationToken) ValueTask<GeolocationPermissionState> Granted, Denied, Prompt, or Unknown where the browser does not expose the permissions api.

IGeolocationService

Method Type Description
GetPositionAsync() ValueTask<ILatLong> Triggers the browser's geolocation prompt and returns the coordinates, or null when there are none.
GetGeoLocationGrantedAsync() ValueTask<bool> Whether the permission is already granted. false also means "not asked yet".
DisposeAsync() ValueTask Disposes of the JavaScript module reference.

GeolocationFailureReason

Value Meaning
None The reading succeeded.
PermissionDenied The user, the browser, or a Permissions-Policy header refused it.
PositionUnavailable The device has no way to know where it is.
Timeout Nothing answered within the configured budget.
NotSupported The browser does not expose the geolocation api. Inside an iframe it also needs allow="geolocation".
InsecureContext The page is not served over https or from localhost.
Unknown Anything else, with the browser message in FailureMessage.

Developed for BlazorBasics.Maps

You can use in conjuntion with BlazorBasics.Maps.Google and BlazorBasics.Maps.Leaflet or any other application.

Contributing

If you encounter issues or have suggestions for improvements, please submit an issue or pull request to the repository hosting this library.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.2 326 8/4/2026
1.2.1 490 1/16/2026
1.2.0 141 1/5/2026

Every position request now carries a timeout, so a request that gets no answer from
 the browser ends instead of waiting forever. Falls back to a low accuracy request
 when the gps fix does not arrive. New IExtendedGeolocationService returns why a
 reading failed (permission, unavailable, timeout, not supported, insecure context)
 instead of a null position. Reading the permission no longer throws where
 navigator.permissions does not exist.