Skip to main content

.NET SDK

The .NET SDK provides a C# interface for interacting with Terragnos Core. It targets .NET 8+ and is distributed via NuGet.

Installation

Package Manager

Install-Package Terragnos.AdminSdk

.NET CLI

dotnet add package Terragnos.AdminSdk

PackageReference

<PackageReference Include="Terragnos.AdminSdk" Version="1.0.0" />

Requirements

  • .NET 8.0 or later
  • System.Net.Http (included)

Basic Usage

Creating a Client

using Terragnos.AdminSdk;

var client = new TerragnosAdminClient(
baseUrl: "https://core.example.com/v1",
token: Environment.GetEnvironmentVariable("TERRAGNOS_TOKEN")
);

Using Statement

The client implements IAsyncDisposable:

await using var client = new TerragnosAdminClient(
baseUrl: "https://core.example.com/v1",
token: token
);

Listing Objects

var result = await client.ListObjectsAsync(
typeId: "traffic-signal",
limit: 25
);

Console.WriteLine($"Found {result.Items.Count} objects");
foreach (var obj in result.Items)
{
Console.WriteLine($"{obj.PublicId}: {obj.TypeId}");
}

Creating Objects

var newObject = await client.CreateObjectAsync(new CreateObjectRequest
{
TypeId = "traffic-signal",
Attributes = new Dictionary<string, object>
{
{ "signalType", "standard" },
{ "intersectionId", "INT-001" }
},
Geometry = new Geometry
{
Type = "Point",
Coordinates = new[] { 19.04, 47.49 }
}
});

Console.WriteLine($"Created object: {newObject.Id}");

Updating Objects

var updated = await client.UpdateObjectAsync(
objectId: "object-id",
version: 1, // Optimistic locking
attributes: new Dictionary<string, object>
{
{ "signalType", "pedestrian" }
}
);

Workflow Transitions

await client.TransitionWorkflowAsync(
objectId: "object-id",
targetState: "approved",
metadata: new Dictionary<string, object>
{
{ "reason", "Meets all requirements" }
}
);

Query Service

var queryResult = await client.RunQueryAsync(new ExecuteQueryRequest
{
Filters = new[]
{
new QueryFilter
{
Field = "typeId",
Operator = "equals",
Value = "traffic-signal"
},
new QueryFilter
{
Field = "attributes.status",
Operator = "equals",
Value = "active"
}
},
Sorts = new[]
{
new QuerySort
{
Field = "createdAt",
Order = "desc"
}
},
Limit = 50
});

Error Handling

try
{
var obj = await client.GetObjectAsync("object-id");
}
catch (TerragnosException ex)
{
switch (ex.StatusCode)
{
case 401:
Console.Error.WriteLine("Authentication failed");
break;
case 403:
Console.Error.WriteLine("Permission denied");
break;
case 404:
Console.Error.WriteLine("Object not found");
break;
case 409:
Console.Error.WriteLine("Optimistic locking conflict");
break;
default:
Console.Error.WriteLine($"API error: {ex.Message}");
break;
}
}

Custom HttpClient

Inject your own HttpClient for custom configuration:

var httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};

var client = new TerragnosAdminClient(
baseUrl: "https://core.example.com/v1",
token: token,
httpClient: httpClient
);

Available Operations

View all available operations:

foreach (var operation in TerragnosAdminClient.AvailableOperations)
{
Console.WriteLine(operation);
}

Dependency Injection

Register the client in your DI container:

services.AddSingleton<TerragnosAdminClient>(provider =>
{
var config = provider.GetRequiredService<IConfiguration>();
return new TerragnosAdminClient(
baseUrl: config["Terragnos:BaseUrl"],
token: config["Terragnos:Token"]
);
});

Best Practices

  1. Use async/await – All operations are asynchronous
  2. Dispose properly – Use await using or call DisposeAsync()
  3. Handle exceptions – Always catch TerragnosException
  4. Reuse clients – Create one client instance per application
  5. Configure HttpClient – Set appropriate timeouts and retry policies
  6. Use configuration – Store base URL and token in configuration
  7. Type safety – Leverage C# types for compile-time safety