The Kodall .NET SDK enables .NET applications (C#, F#, VB.NET) to interact with Kodall platform services, execute entity CRUD operations, process hierarchical models with children, run declarative Fetch queries, and trigger server-side workflows.
Install the Kodall .NET package and serialization dependencies via the .NET CLI or Package Manager:
dotnet add package Kodall.Sdk
dotnet add package System.Runtime.Serialization.Primitives
Install-Package Kodall.Sdk
Install-Package System.Runtime.Serialization.Primitives
<ItemGroup>
<PackageReference Include="Kodall.Sdk" Version="1.0.0" />
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
</ItemGroup>
Initialize the client with your backend server URL and API key:
using System;
using System.Threading.Tasks;
using Kodall.Sdk;
public class Program
{
public static async Task Main(string[] args)
{
// Configure client
var options = new KodallClientOptions
{
BaseUrl = "https://docs-demo.kodall.io",
ApiKey = "e3097afe-1528-4fdb-a816-0d3724a8f318"
};
var client = new KodallClient(options);
// Execute fetch query
var query = "FETCH todo (key, title, is_completed) ORDER BY key DESC LIMIT 5";
var todos = await client.FetchAsync(query);
foreach (var todo in todos)
{
Console.WriteLine($"Todo #{todo["key"]}: {todo["title"]}");
}
}
}
Configure the client via KodallClientOptions:
using System;
using Kodall.Sdk;
// Stateless API Key mode
var apiKeyOptions = new KodallClientOptions
{
BaseUrl = "https://docs-demo.kodall.io",
ApiKey = "e3097afe-1528-4fdb-a816-0d3724a8f318",
Timeout = TimeSpan.FromSeconds(30)
};
var client = new KodallClient(apiKeyOptions);
// Stateful Session Cookie mode
var sessionOptions = new KodallClientOptions
{
BaseUrl = "https://docs-demo.kodall.io",
Timeout = TimeSpan.FromSeconds(30)
};
var sessionClient = new KodallClient(sessionOptions);
| Option | Type | Description |
|---|---|---|
BaseUrl | string | Base server endpoint URL (e.g. https://docs-demo.kodall.io). |
ApiKey | string | Optional secret API key for stateless X-API-Key authentication. |
Timeout | TimeSpan | HTTP request execution timeout (default: 30s). |
The .NET SDK supports both stateless API Key authentication and stateful Session Cookie authentication:
using System;
using Kodall.Sdk;
using Kodall.Sdk.Exceptions;
var client = new KodallClient(new KodallClientOptions { BaseUrl = "https://docs-demo.kodall.io" });
try
{
var session = await client.AuthenticateAsync("root", "password123", "ro");
Console.WriteLine($"Authenticated user: {session.UserName}");
}
catch (KodallAuthenticationException ex)
{
Console.WriteLine($"Authentication failed: {ex.Message}");
}
var session = await client.AuthenticateOidcAsync("eyJhbGciOi...", "optionalRefreshToken");
// Fetch current session details with roles and profiles
var session = await client.GetSessionAsync(includeRoles: true, includeProfiles: true);
// Switch active user profile
await client.ChangeUserProfileAsync("sales_admin");
// Terminate active session
await client.LogoutAsync();
For more authentication details, visit the Auth API Reference.
Define strongly-typed entity models using .NET [DataContract] and [DataMember] attributes:
using System.Runtime.Serialization;
using Kodall.Sdk;
[DataContract]
public class Product : IEntityProperties
{
public long? Key { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "price")]
public decimal Price { get; set; }
}
using System.Collections.Generic;
using System.Runtime.Serialization;
using Kodall.Sdk;
[DataContract]
public class MenuNode : IEntityProperties
{
public long? Key { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
}
[DataContract]
public class MenuNodeItem : IEntityProperties
{
public long? Key { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
}
[DataContract]
public class MenuNodeChildren
{
[DataMember(Name = "menu_node_menu_node_item")]
public List<SimpleEntity<MenuNodeItem>> Items { get; set; }
}
Execute strongly typed create, read, update, and delete operations:
using System;
using Kodall.Sdk;
using Kodall.Sdk.Exceptions;
try
{
// 1. Create Entity
var newProduct = new Product { Name = "Developer Laptop", Price = 1999.99m };
var created = await client.CreateAsync<Product, Empty>("product", newProduct);
long key = created.Key;
Console.WriteLine($"Created Product Key: {key}");
// 2. Read Entity
var productEntity = await client.GetAsync<Product, Empty>("product", key);
Console.WriteLine($"Retrieved: {productEntity.Properties.Name}");
// 3. Update Entity
productEntity.Properties.Price = 1799.99m;
await client.UpdateAsync<Product, Empty>("product", key, productEntity.Properties);
// 4. Delete Entity
await client.DeleteAsync("product", key);
}
catch (KodallValidationException ex)
{
Console.WriteLine($"Validation constraint failed on {ex.PropertyName}: {ex.Detail}");
}
catch (KodallApiException ex)
{
Console.WriteLine($"API Error [{ex.StatusCode}]: {ex.Message}");
}
For more entity operations and payload structures, visit the Entities API Reference.
Execute declarative graph queries or inspect result columns:
// Execute query
var rows = await client.FetchAsync(@"
FETCH todo (key, title, is_completed) {
todo_item TO id_todo (key AS item_key, description, is_completed AS item_completed)
}
FILTER AND (is_completed == 0)
ORDER BY key DESC
LIMIT 10
");
// Parse Query AST
var ast = await client.ParseQueryAsync("FETCH todo (key, title)");
// Inspect Columns Metadata
var metadata = await client.FetchMetadataAsync("FETCH todo (key, title)");
For more query syntax options, visit the Fetch API Reference.
Execute server-side workflows and deserialize typed responses:
public class ConcatArgs
{
public string Arg1 { get; set; }
public string Arg2 { get; set; }
public string Glue { get; set; }
}
public class ConcatResponse
{
public string Concat { get; set; }
}
var concatArgs = new ConcatArgs
{
Arg1 = "Hello",
Arg2 = "Kodall",
Glue = " "
};
var response = await client.RunWorkflowAsync<ConcatResponse, ConcatArgs>("test", "concat", concatArgs);
Console.WriteLine($"Result: {response.Concat}");
For more workflow examples, visit the Workflow API Reference.
Upload, download, and version files directly using standard streams or byte arrays:
using System.IO;
// 1. Upload a file
byte[] fileBytes = await File.ReadAllBytesAsync("report.pdf");
var items = await client.UploadFileAsync(fileBytes, "report.pdf", "application/pdf");
long fileId = items[0].Id;
// 2. Upload a new version
byte[] updatedBytes = await File.ReadAllBytesAsync("report_v2.pdf");
await client.UploadFileVersionAsync(updatedBytes, "report.pdf", fileId);
// 3. Download file bytes
byte[] downloaded = await client.GetFileAsync(fileId, action: "download");
await File.WriteAllBytesAsync("downloaded_report.pdf", downloaded);
For more storage operations, visit the Storage API Reference.
The .NET SDK throws structured typed exceptions:
using Kodall.Sdk.Exceptions;
try
{
await client.CreateAsync("invalid_entity", payload);
}
catch (KodallValidationException ex)
{
// HTTP 424: Business rule validation constraint violated
Console.WriteLine($"Validation failed on property {ex.PropertyName}: {ex.Detail}");
}
catch (KodallAuthenticationException ex)
{
// HTTP 401: Invalid credentials or expired session
Console.WriteLine($"Authentication error: {ex.Message}");
}
catch (KodallForbiddenException ex)
{
// HTTP 403: Access forbidden
Console.WriteLine($"Permission denied: {ex.Message}");
}
catch (KodallNotFoundException ex)
{
// HTTP 404: Resource not found
Console.WriteLine($"Not found: {ex.Message}");
}
catch (KodallApiException ex)
{
// General API error (400, 500, etc.)
Console.WriteLine($"API Error ({ex.StatusCode}): {ex.Message}");
}