Kodall
Client SDKs

.NET SDK

Integrate .NET and C# backend applications with Kodall platform entity services, authentication, and workflows.

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.


Requirements

  • .NET 6.0, .NET 7.0, .NET 8.0, or .NET Framework 4.8+
  • Compatible with C# 10+ and modern NuGet package tooling.

Installation

Install the Kodall .NET package and serialization dependencies via the .NET CLI or Package Manager:

BASH
dotnet add package Kodall.Sdk
dotnet add package System.Runtime.Serialization.Primitives

Quickstart

Initialize the client with your backend server URL and API key:

CSHARP
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"]}");
        }
    }
}

Client Configuration

Configure the client via KodallClientOptions:

CSHARP
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);
OptionTypeDescription
BaseUrlstringBase server endpoint URL (e.g. https://docs-demo.kodall.io).
ApiKeystringOptional secret API key for stateless X-API-Key authentication.
TimeoutTimeSpanHTTP request execution timeout (default: 30s).

Authentication

The .NET SDK supports both stateless API Key authentication and stateful Session Cookie authentication:

Basic Authentication (Username & Password)

CSHARP
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}");
}

OpenID Connect (OIDC / OAuth2)

CSHARP
var session = await client.AuthenticateOidcAsync("eyJhbGciOi...", "optionalRefreshToken");

Session Lifecycle & Logout

CSHARP
// 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.


Defining Entity Models

Define strongly-typed entity models using .NET [DataContract] and [DataMember] attributes:

CSHARP
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; }
}

Entity CRUD Operations

Execute strongly typed create, read, update, and delete operations:

CSHARP
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.


Fetch Query Engine

Execute declarative graph queries or inspect result columns:

CSHARP
// 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.


Custom Workflows

Execute server-side workflows and deserialize typed responses:

CSHARP
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.


File Storage & Versioning

Upload, download, and version files directly using standard streams or byte arrays:

CSHARP
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.


Error Handling

The .NET SDK throws structured typed exceptions:

CSHARP
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}");
}

Next Steps