IPGeoTrace.Client.AspNetCore 0.0.1

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

IPGeoTrace ASP.NET Core Integration

ASP.NET Core integration for the IPGeoTrace IP geolocation API, built on the IPGeoTrace.Client package.

Sign up and grab your API key at app.ipgeotrace.com.

Install

dotnet add package IPGeoTrace.Client.AspNetCore

Targets net8.0.

Register the client

One line in Program.cs:

builder.Services.AddIpGeoTrace(builder.Configuration["IpGeoTrace:ApiKey"]!);

That is all the setup there is. Every setting is optional and covered in Configuration below.

From here you have two independent ways to use the library. The middleware is optional. Pick whichever fits, or use both.

Option 1: Use the client directly

Inject IIpGeoTraceClient into any controller or service and resolve whatever IP you supply: a signup form, a webhook payload, a stored audit log. Where the IP comes from is entirely your call. Nothing about this touches the request pipeline, and no UseIpGeoTrace call is needed.

Screen new signups for datacenter IPs and country mismatches:

public sealed class SignupScreening(IIpGeoTraceClient geo)
{
    public async Task<bool> NeedsReviewAsync(string signupIp, string billingCountry, CancellationToken ct)
    {
        var result = await geo.ResolveAsync(signupIp, ct);
        if (!result.IsSuccess)
            return false;

        var fromDatacenter = result.Value.Asn?.Type == "hosting";
        var countryMismatch = result.Value.Country?.Code is { } code && code != billingCountry;
        return fromDatacenter || countryMismatch;
    }
}

Enrich a page of audit records in one round trip with a batch lookup:

var batch = await geo.ResolveBatchAsync(logins.Select(l => l.IpAddress), ct);
if (batch.IsSuccess)
    foreach (var item in batch.Value.Results)
        report.Add(item.Ip, item.Country?.Name, item.Asn?.Name);

See the IPGeoTrace.Client README for the full client documentation.

Option 2: Resolve the caller automatically

This is what this package adds: middleware that determines the caller's IP, resolves it once per request, and hands you the result anywhere via HttpContext.GetGeo(). No IP handling in your code at all.

Add it after UseRouting. Endpoint metadata such as [SkipGeo] is only visible to the middleware once routing has run:

var app = builder.Build();

app.UseRouting();
app.UseIpGeoTrace();
app.MapControllers();

Show prices in the visitor's currency:

[HttpGet("checkout")]
public IActionResult Checkout()
{
    var geo = HttpContext.GetGeo();
    var currency = geo.IsResolved ? geo.Value.Country?.Currency ?? "USD" : "USD";
    return Ok(_catalog.PricedIn(currency));
}

Route the visitor to the nearest warehouse from a minimal API:

app.MapGet("/shipping-estimate", (HttpContext http) =>
{
    return http.GetGeo().TryGetValue(out var visitor)
        ? Results.Ok(Warehouses.NearestTo(visitor.Location?.Latitude, visitor.Location?.Longitude))
        : Results.Ok(Warehouses.Default);
});

GeoLookup.Status tells you exactly what happened:

  • Resolved: Value carries the data, and FromCache says whether an API call was made.
  • Skipped: the caller's address was missing, invalid, private, link-local, or loopback, so no API call was made.
  • Failed: Error carries the reason, such as rate_limited or quota_exceeded.
  • NotAttempted: the middleware did not run for this request, the endpoint opted out, or ShouldResolve returned false.

GetGeo() is always safe to call. It never throws for a missing lookup and reports NotAttempted when the middleware is not registered.

Skipping endpoints

Health checks, metrics, and internal endpoints should not spend lookups. Opt them out with the attribute:

[HttpGet("health")]
[SkipGeo]
public IActionResult Health() => Ok();

with the minimal API convention:

app.MapGet("/metrics", () => Results.Ok()).SkipGeo();

or centrally with a predicate:

app.UseIpGeoTrace(options =>
{
    options.ShouldResolve = context => !context.Request.Path.StartsWithSegments("/internal");
});

Choosing the caller's IP

By default the middleware uses Connection.RemoteIpAddress. Behind a proxy or load balancer, configure the standard forwarded-headers middleware before UseIpGeoTrace instead of parsing headers yourself:

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor
});

For full control, supply your own selector:

app.UseIpGeoTrace(options =>
{
    options.IpAddressSelector = context => context.Connection.RemoteIpAddress?.ToString();
});

Private, link-local, and loopback addresses (including IPv4-mapped IPv6 forms) are detected locally and skipped without an API call or quota usage.

Configuration

All settings live on the AddIpGeoTrace options callback. Each one is optional.

Caching

Off by default. Turn it on and repeat lookups of the same IP are served from memory: no API call, no latency, and nothing counted against your monthly quota. Returning visitors become free after their first request.

builder.Services.AddIpGeoTrace(apiKey, options =>
{
    options.CacheEnabled = true;
});

Only successful lookups are cached, never errors. Batch calls share the same cache, so only the misses are sent to the API.

Cache lifetime

How long a cached lookup stays valid. The default is 5 minutes.

options.CacheTtl = TimeSpan.FromHours(6);

Your own cache store

Supply any IGeoCache implementation (Redis, distributed cache, anything) and caching turns on automatically. If you register an IGeoCache in the container instead, it is picked up without any option at all. A throwing store never breaks a lookup; the client falls back to calling the API directly.

options.Cache = new RedisGeoCache(connection);

Timeout

Per-request timeout. The default is 10 seconds.

options.Timeout = TimeSpan.FromSeconds(3);

Retries

Rate limits (429) and outages (503) are retried automatically, honoring the API's Retry-After header. The default is 2 retries. Set it to 0 if you chain your own resilience handler (for example Polly) on the IHttpClientBuilder that AddIpGeoTrace returns, so requests are not retried twice.

options.MaxRetries = 0;
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 was computed.  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 was computed.  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
0.0.1 119 7/2/2026