MapLargeInc.RestClient 4.135.20260718.21250

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

MapLarge.RestClient

A strongly-typed .NET client for the MapLarge Server REST API. It provides:

  • A single typed entry point (RestClient) with a property per API area — accounts, tables, queries, imports, layers, reports, workflows, cluster diagnostics, and many more.
  • Automatic authentication and token refresh.
  • Typed request and response models, with helpers for HAL list responses, paging, and long-running (poll-to-complete) requests.
  • First-class support for client-certificate (mTLS) servers.

The package multi-targets .NET Standard 2.0 and .NET 8.0. The netstandard2.0 target supports .NET Framework 4.6.1+, .NET Core 2.0+, and .NET 5+; consumers on .NET 8 or later automatically pick up the net8.0 target for access to newer BCL APIs.

Installation

Add the package with the .NET CLI:

$ dotnet add package MapLargeInc.RestClient

Or reference a specific version in your .csproj:

<PackageReference Include="MapLargeInc.RestClient" Version="[package version number]" />

Note: The package id is MapLargeInc.RestClient; it provides the MapLarge.RestClient assembly and the MapLarge.Rest.* namespaces (so you still write using MapLarge.Rest.Client;). If your project isn't configured for the feed it's published to, add it as a package source (via a nuget.config, or with dotnet add package MapLargeInc.RestClient --source [feed url]).

Quick start

Construct a client with your server URL and credentials, then call any endpoint through its typed group property. Every endpoint method is async.

using MapLarge.Rest.Client;

var uri = new Uri("https://your-maplarge-server/");
var creds = new PasswordCredentials("user@maplarge.com", "password");
using var client = new RestClient(uri, creds);

var response = await client.Accounts.ListAsync();
foreach (var account in RestClient.Items(response)) {
    Console.WriteLine(account.Code);
}

Tip: RestClient is thread-safe and designed to be long-lived. Create one per server and reuse it for the lifetime of your process rather than constructing one per call.

Authentication

Pass either password or token credentials to the constructor. Both send the mluser header on every request, along with mlpass or mltoken respectively.

Password credentials

var creds = new PasswordCredentials("user@maplarge.com", "password");
using var client = new RestClient(uri, creds);

On the first call, the client exchanges your username/password for a bearer token via POST /Auth/Login, then uses that token for subsequent requests. When the token nears expiry the client re-authenticates automatically — concurrent callers are coordinated so only one login round-trip is issued.

Token credentials

If you already hold a valid token, use it directly and skip the login round-trip:

var creds = new TokenCredentials("user@maplarge.com", token);
using var client = new RestClient(uri, creds);

You can also supply an explicit lifetime so the client knows when to refresh:

var creds = new TokenCredentials(
    "user@maplarge.com", token, lifespan: TimeSpan.FromHours(1), now: DateTimeOffset.UtcNow);

Note: The early-refresh threshold is the constructor's minRemainingLife parameter (default 0.5) — the fraction of a token's lifetime that must remain before the client proactively re-authenticates. It only applies to credentials that carry a lifetime.

Calling endpoints

Each API area is a typed property on the client, and each operation is an async method returning a typed model. Path segments are method parameters; request bodies are typed model objects.

// GET /accounts/{account}
Account account = await client.Accounts.GetAsync("myaccount");

// GET /tables/{account}/{name}
TableVersion table = await client.Tables.GetAsync("myaccount", "mytable");

// POST a typed request body
Account created = await client.Accounts.PostAsync(new CreateAccountRequest { /* ... */ });

The available groups mirror the server's REST surface — Accounts, Tables, Queries, Imports, Layers, Reports, Users, Groups, Workflows, Cluster, Diagnostics, Extensions, and many more. Every group is a property on RestClient, so IntelliSense lists them all, along with each group's operations and their parameters.

Tip: Models live in the MapLarge.Rest.Models namespace. Add using MapLarge.Rest.Models; to reference request/response types such as Query, TableVersion, or PageOptions directly.

Working with list responses

List endpoints return a JSON HAL wrapper (RestList<T>) whose records live under an _embedded block, alongside paging links. Use the static RestClient.Items helper to unwrap them; it returns an empty list rather than null when the response has no embedded items.

var response = await client.Accounts.ListAsync();
foreach (var account in RestClient.Items(response)) {
    Console.WriteLine(account.Code);
}

Paging

When you request a page size, the server returns a Page<T> (a RestList<T> with next/prev links). Follow _links.next with FollowAsync to walk every page, unwrapping each the same way:

using MapLarge.Rest.Models;

var page = (Page<TableVersion>)await client.Tables.ListAsync("myaccount", new PageOptions { Size = 100 });
while (page != null) {
    foreach (var table in RestClient.Items(page)) {
        Console.WriteLine(table.Name);
    }
    page = page.Links.Next != null
        ? await client.FollowAsync<Page<TableVersion>>(page.Links.Next)
        : null;
}

Note: FollowAsync<T> works with any HAL link the server returns — not just paging. Use it to follow Import.Links.Result after an import completes, LongRunningTask.Links.Self while polling, or any other _links entry. It accepts either a Link or an href string (absolute or relative to the client's base URL).

Long-running requests (fallback-to-poll)

Endpoints that may exceed the server's synchronous request budget can be configured to transparently fall back to polling. Set FallbackToPollSettings on a RequestOptions; when the server responds 202 Accepted, the client polls the resulting LongRunningTask to completion and returns the final result as if the call had been synchronous. Supply a ProgressCallback to observe each poll iteration.

using MapLarge.Rest.Models;

var options = new RequestOptions {
    FallbackToPollSettings = new FallbackToPollSettings {
        FallbackToPoll = true,
        PollIntervalSeconds = 1.0,
        ProgressCallback = task => Console.WriteLine($"task {task.Id} progress: {task.Progress}"),
    },
};
var result = await client.Queries.ResultDirectAsync(query, options);

Polling an import to completion

Import endpoints (Tables.PostAsync, Tables.UploadAsync) start the work and return an Import immediately — the server responds 202 Accepted while it keeps processing. Poll the import's Links.Self until Successful has a value, then follow Links.Result for the created table:

using MapLarge.Rest.Models;

var import = await client.Tables.PostAsync("myaccount", "mytable", new CreateTableRequest {
    Data = "ID,Lat,Lng,Name\r\n1,0.0,0.0,One\r\n2,10.0,10.0,Two",
    Visibility = TableVisibility.Public,
});

var deadline = DateTimeOffset.UtcNow + TimeSpan.FromMinutes(5);
while (!import.Successful.HasValue) {
    if (DateTimeOffset.UtcNow >= deadline)
        throw new TimeoutException($"Import {import.Id} did not complete within the timeout.");
    await Task.Delay(TimeSpan.FromSeconds(1));
    import = await client.FollowAsync<Import>(import.Links.Self);
}

var rows = await client.FollowAsync<RestList<TableVersion>>(import.Links.Result!);

Request options

Pass a RequestOptions to any endpoint method to control cluster routing and read-after-write consistency:

Property Purpose
MlServerFwd Pin the request to a specific node within the cluster.
ProxyToClusterKey / ProxyToDomain Execute the request against a different MapLarge cluster (by key or by URL).
WaitForTransactionId Require the processing node to have applied a given transaction before serving the request — chain a read after a write without observing stale state (use the waitForTransactionId response header from the prior mutation).
FallbackToPollSettings Opt in to poll-to-complete handling for long-running requests (see above).

Note: RequestOptions does not carry a per-request timeout — .NET's HttpClient honors a single client-wide timeout only. For per-request deadlines, pass a CancellationToken:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var account = await client.Accounts.GetAsync("myaccount", cancellationToken: cts.Token);

Authenticating with a client certificate (mTLS)

When a MapLarge server is configured with RequireClientCertificate=true, callers must present a TLS client certificate before the application sees the request. Attach the certificate to an HttpClient and pass it to the RestClient constructor. The mluser / mltoken / mlpass credential headers coexist with certificate-based TLS authentication — both layers can be required by the server.

using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using MapLarge.Rest.Client;

var clientCert = new X509Certificate2("client.pfx", "passphrase");

var handler = new HttpClientHandler();
handler.ClientCertificates.Add(clientCert);

// Optional: trust a private CA for the server cert. Skip if the server cert chains
// to a public root already trusted by the OS.
// handler.ServerCertificateCustomValidationCallback = (msg, cert, chain, errors) => /* validate */;

using var http = new HttpClient(handler);
using var client = new RestClient(
    new Uri("https://maplarge.example/"),
    new PasswordCredentials("user@maplarge.com", "password"),
    http);

var accounts = await client.Accounts.ListAsync();

Note: On .NET Framework the same pattern works unchanged. To load the certificate from the Windows certificate store, use X509Store with X509FindType.FindByThumbprint.

Caveats

  • Reuse a single HttpClient for the process lifetime rather than constructing one per request — TLS handshakes are expensive. Dispose the X509Certificate2 when you're done with it.
  • ServerCertificateCustomValidationCallback overrides the entire chain validation. Use it only to add a trusted private CA; don't blanket-return true in production.

Common examples

Import a table from a file

Upload one or more files with BinaryContent and Tables.UploadAsync. Like other imports, this returns an Import you can poll to completion (see Polling an import to completion).

using System.Collections.Generic;
using MapLarge.Rest.Client;
using MapLarge.Rest.Models;

using var stream = File.OpenRead("wildfires.csv");
var file = new BinaryContent(stream, "wildfires.csv", "text/csv");

var import = await client.Tables.UploadAsync(
    account: "myaccount",
    name: "wildfires",
    body: new CreateTableFromFileUploadRequest {
        Files = new List<BinaryContent> { file },
        PrimaryKeyColumn = "FIREID",
    });

Export a table

Tables.Versions.ExportAsync returns a BinaryContent whose Stream holds the exported bytes — copy it to a file (or any destination stream):

using MapLarge.Rest.Models;

using var export = await client.Tables.Versions.ExportAsync(
    account: "myaccount",
    name: "wildfires",
    version: "latest",
    accept: TablesVersionsExportAcceptType.application_geo_json);

using var file = File.Create("wildfires.geojson");
await export.Stream!.CopyToAsync(file);

Run a query (hash & cache)

Query and Layer entities use a hash & cache workflow. Posting a query returns its server-computed Hash; the server caches results by that hash, so an identical query isn't recomputed. Use ExistsAsync to check whether a result is available for a hash, then ResultAsync to fetch it.

using MapLarge.Rest.Models;

var query = new Query {
    Table = new QueryTable { Name = "myaccount/wildfires" },
    Where = new QueryWhereTest {
        Column = "CAUSE",
        Test = "Equal",
        Value = QueryWhereLiteral.Of("Natural"),
    },
    Take = -1,   // -1 = no row limit
};

var posted = await client.Queries.PostAsync(query);
if (await client.Queries.ExistsAsync(posted.Hash)) {
    var result = await client.Queries.ResultAsync(posted.Hash);

    // DBResult.Data is column-oriented: a map of column name -> list of values.
    var ids = result.Data["FIREID"];
    var names = result.Data["FIRENAME"];
    for (var i = 0; i < ids.Count; i++) {
        Console.WriteLine($"{ids[i]}, {names[i]}");
    }
}

Render a layer tile

Layers follow the same hash & cache workflow. Post a Layer (a Query plus a Style) to get its Hash, then render map tiles by hash. TileAsync renders a single XYZ tile and returns the image bytes as a BinaryContent; it takes a list of hashes, so you can composite several layers into one tile.

using System.Collections.Generic;
using MapLarge.Rest.Models;

var layer = new Layer {
    Query = new Query { Table = new QueryTable { Name = "myaccount/wildfires" } },
    Style = new Style { DrawShapes = true },
};

// The server caches layers by content and returns a hash. Before rendering with a hash you
// stored earlier, confirm it's still cached with ExistsAsync and re-post if it isn't.
var hash = (await client.Layers.PostAsync(layer)).Hash;
if (!await client.Layers.ExistsAsync(hash)) {
    hash = (await client.Layers.PostAsync(layer)).Hash;
}

using var tile = await client.Layers.TileAsync(
    zoom: 4, x: 2, y: 6,
    format: ImageFormatType.png,
    hashes: new List<string> { hash });

using var file = File.Create("tile.png");
await tile.Stream!.CopyToAsync(file);

Note: Layers also offers ImageAsync (a single static map image at fixed dimensions rather than an XYZ tile), plus ClickAsync and HoverGridAsync for interactive lookups at a pixel.

Tip: Full request/response schemas for every endpoint are in the server's Swagger UI (available from the MapLarge server's API documentation).

Error handling

A non-2xx response throws a RestException (namespace MapLarge.Rest.Exceptions) carrying the request Uri, HTTP Status, raw ResponseText, and parsed Details (a ProblemDetails).

using MapLarge.Rest.Exceptions;

try {
    var table = await client.Tables.GetAsync("myaccount", "mytable");
}
catch (RestValidationException ex) {
    // HTTP 400 with per-field validation errors.
    foreach (var entry in ex.ValidationDetails.Errors) {
        Console.WriteLine($"{entry.Key}: {string.Join(", ", entry.Value)}");
    }
}
catch (RestException ex) {
    Console.WriteLine($"{ex.Status} calling {ex.Uri}: {ex.ResponseText}");
}
  • RestValidationException (derives from RestException) is thrown for 400 responses with a ValidationProblemDetails body; catch it first when you want per-field messages (ValidationDetails.Errors, a map of field name to messages).
  • AuthenticationException is thrown when login fails; it exposes the StatusCode and the server's LoginResponse.

Disposing the client

RestClient implements IDisposable. Dispose it (or wrap it in using) when you're done, to release the underlying HttpClient it owns. If you pass in your own HttpClient (e.g. for mTLS), the client does not dispose it — you retain ownership of its lifetime.

Notes

  • All endpoint methods are async (Task / Task<T>).
  • JSON is serialized via Newtonsoft.Json.
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos 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
4.135.20260718.21250 121 7/18/2026
4.135.20260717.233243 112 7/17/2026