BoxesNLines.Geolocation 1.0.1

dotnet add package BoxesNLines.Geolocation --version 1.0.1
                    
NuGet\Install-Package BoxesNLines.Geolocation -Version 1.0.1
                    
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="BoxesNLines.Geolocation" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BoxesNLines.Geolocation" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="BoxesNLines.Geolocation" />
                    
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 BoxesNLines.Geolocation --version 1.0.1
                    
#r "nuget: BoxesNLines.Geolocation, 1.0.1"
                    
#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 BoxesNLines.Geolocation@1.0.1
                    
#: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=BoxesNLines.Geolocation&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=BoxesNLines.Geolocation&version=1.0.1
                    
Install as a Cake Tool

BoxesNLines.Geolocation - .NET SDK

Official .NET SDK for the BoxesNLines Geolocation API. Provides GeolocationClient for geographic lookups using API key authentication.

Requirements

  • .NET 8.0, 9.0, or 10.0

Architecture

graph LR
    App["Your Application"] --> Client["GeolocationClient"]
    Client --> Cache{"LRU Cache\nenabled?"}
    Cache -->|hit| App
    Cache -->|miss| HTTP["ApiHttpClient"]
    HTTP -->|"X-API-Key"| Gateway["api.boxesnlines.com\n/geo/*"]
    HTTP -->|429| Retry["RateLimitHandler\nRetry-After"]
    HTTP -->|5xx| Backoff["RetryHandler\nExponential Backoff"]
    Retry --> HTTP
    Backoff --> HTTP
    Gateway --> HTTP
    HTTP --> Cache

Installation

dotnet add package BoxesNLines.Geolocation

Quick Start

using BoxesNLines.Geolocation;

using var client = new GeolocationClient(new GeolocationClientOptions
{
    ApiKey = "bnl_your_api_key"
});

// Get country from GPS coordinates (returns ISO 3166-1 alpha-3 code)
var country = await client.GetCountryFromGpsAsync(40.7128, -74.0060);
Console.WriteLine(country.Data); // "USA"

// Get subdivision (returns ISO 3166-2 code)
var subdivision = await client.GetSubdivisionFromGpsAsync(40.7128, -74.0060);
Console.WriteLine(subdivision.Data); // "US-NY"

// Check if coordinates are within a country
var inUs = await client.IsInCountryAsync("USA", 40.7128, -74.0060);
Console.WriteLine(inUs.Data); // true

// Check if coordinates are within a subdivision
var inNy = await client.IsInSubdivisionAsync("US-NY", 40.7128, -74.0060);
Console.WriteLine(inNy.Data); // true

GeolocationClient implements IDisposable. Use using when constructing it directly, or let the DI container manage its lifetime.

Dependency Injection

Register the client with the .NET DI container using the provided extension method:

using BoxesNLines.Geolocation.DependencyInjection;

builder.Services.AddBoxesNLinesGeolocation(opt =>
{
    opt.ApiKey = builder.Configuration["BoxesNLines:ApiKey"]!;
});

Then inject IGeolocationClient into your services:

public class MyService(IGeolocationClient geo)
{
    public async Task<string> GetCountry(double lat, double lon)
    {
        var result = await geo.GetCountryFromGpsAsync(lat, lon);
        return result.Data;
    }
}

Configuration

GeolocationClientOptions

Property Type Default Description
ApiKey string (required) Your BoxesNLines API key
BaseUrl string https://api.boxesnlines.com API base URL
TimeoutSeconds int 30 HTTP request timeout
MaxRetries int 3 Max retries on rate-limit (429) and server errors (5xx)
Cache.Enabled bool true Enable built-in LRU response cache
Cache.DefaultTtl TimeSpan 5 minutes Cache entry lifetime
Cache.MaxEntries int 1000 Max cached entries
CustomCache IGeolocationCache? null Pluggable cache implementation (see below)
NoCacheWarningInterval int 100 Emit a diagnostic trace warning every N requests when caching is disabled. Set to 0 to suppress.

Error Handling

All API errors throw typed exceptions derived from ApiException:

using BoxesNLines.Geolocation.Errors;

try
{
    await client.GetCountryFromGpsAsync(lat, lon);
}
catch (RateLimitException ex)
{
    Console.WriteLine($"Rate limited. Retry after {ex.RetryAfterSeconds}s");
}
catch (AuthException)
{
    Console.WriteLine("Invalid or expired API key");
}
catch (NotFoundException)
{
    Console.WriteLine("No country found for these coordinates");
}
catch (ConflictException)
{
    Console.WriteLine("Request conflict (HTTP 409)");
}
catch (ValidationException ex)
{
    foreach (var (field, errors) in ex.FieldErrors)
        Console.WriteLine($"{field}: {string.Join(", ", errors)}");
}
catch (ApiException ex)
{
    Console.WriteLine($"API error {ex.StatusCode}: {ex.Message}");
}

The SDK automatically retries 429 responses using the Retry-After header value, and retries 5xx responses with exponential backoff. Retries are bounded by MaxRetries.

Rate Limit Information

Every successful response includes rate limit information from the response headers:

var response = await client.GetCountryFromGpsAsync(lat, lon);
Console.WriteLine($"Burst: {response.RateLimitInfo.BurstRemaining}/{response.RateLimitInfo.BurstLimit}");
Console.WriteLine($"Quota: {response.RateLimitInfo.QuotaRemaining}/{response.RateLimitInfo.QuotaLimit}");

Caching

The SDK ships with a thread-safe in-memory LRU cache enabled by default. Cache keys are derived from the request path (e.g. GET:/geo/country/fromGps/40.712800,-74.006000).

To clear the cache:

await client.ClearCacheAsync();

To disable the built-in cache:

var client = new GeolocationClient(new GeolocationClientOptions
{
    ApiKey = "bnl_your_api_key",
    Cache = new CacheOptions { Enabled = false }
});

Custom Cache

Provide any distributed or custom cache by implementing IGeolocationCache and setting CustomCache. When CustomCache is set, the built-in LRU cache is bypassed entirely.

public sealed class MyRedisCache : IGeolocationCache
{
    private readonly IConnectionMultiplexer _multiplexer;
    private readonly IDatabase _db;

    public MyRedisCache(IConnectionMultiplexer redis)
    {
        _multiplexer = redis;
        _db = redis.GetDatabase();
    }

    public async Task<T?> GetAsync<T>(string key, CancellationToken ct = default)
    {
        var value = await _db.StringGetAsync(key);
        return value.HasValue ? JsonSerializer.Deserialize<T>(value!) : default;
    }

    public async Task SetAsync<T>(string key, T value, TimeSpan? ttl = null, CancellationToken ct = default)
    {
        var json = JsonSerializer.Serialize(value);
        await _db.StringSetAsync(key, json, ttl);
    }

    public async Task RemoveAsync(string key, CancellationToken ct = default) =>
        await _db.KeyDeleteAsync(key);

    public async Task ClearAsync(CancellationToken ct = default)
    {
        var endpoints = _multiplexer.GetEndPoints();
        foreach (var endpoint in endpoints)
        {
            var server = _multiplexer.GetServer(endpoint);
            var keys = server.Keys(pattern: "GET:*");
            foreach (var key in keys)
                await _db.KeyDeleteAsync(key).ConfigureAwait(false);
        }
    }
}

var client = new GeolocationClient(new GeolocationClientOptions
{
    ApiKey = "bnl_your_api_key",
    CustomCache = new MyRedisCache(connectionMultiplexer)
});

The ClearAsync implementation uses server.Keys(pattern: "GET:*") to delete only SDK-owned keys, avoiding collateral damage on a shared Redis instance.

A complete Redis adapter example is available in samples/redis-cache/.

Samples

Sample Description
samples/quickstart/ Minimal usage : reverse geocode three cities, print alpha-3 codes
samples/redis-cache/ Custom Redis-backed IGeolocationCache adapter using GET:* key scoping
samples/gdpr-compliance/ ASP.NET Core Web API enforcing GDPR policy based on visitor country

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  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.0.1 95 5/21/2026
1.0.0 124 3/18/2026