> ## Documentation Index
> Fetch the complete documentation index at: https://taskdaemon.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Csharp

# C# SDK

The C# SDK for writing TaskDaemon handlers.

## Installation

```bash theme={null}
dotnet add package TaskDaemon.Handler
```

## Basic Usage

```csharp theme={null}
using TaskDaemon;

Handler.Run(task => {
    var name = task.task_data.GetValueOrDefault("name", "World");
    return new Success(new { message = $"Hello, {name}!" });
});
```

## Task Record

```csharp theme={null}
public record Task(
    string task_id,
    string task_type,
    Dictionary<string, object> task_data,
    int attempt  // Current attempt (starts at 0)
);
```

## Result Types

```csharp theme={null}
// Abstract base
public abstract record Result;

// Success with result
public record Success(object result) : Result;

// Error with message and optional retryable flag
public record Error(string error, bool retryable = false) : Result;
```

Usage:

```csharp theme={null}
// Success
return new Success(new { processed = true });

// Non-retryable error (default)
return new Error("Invalid input");

// Retryable error
return new Error("Service unavailable", retryable: true);
```

## Complete Example

```csharp theme={null}
using TaskDaemon;
using System.Text.RegularExpressions;

Handler.Run(task => {
    var text = task.task_data.GetValueOrDefault("text", "")?.ToString() ?? "";
    
    // Count words
    var words = Regex.Matches(text, @"\S+").Count;
    
    // Count characters (excluding spaces)
    var chars = text.Count(c => !char.IsWhiteSpace(c));
    
    // Count lines
    var lines = text.Split('\n').Length;
    
    return new Success(new {
        words,
        characters = chars,
        lines
    });
});
```

## Error Handling

Exceptions are automatically caught and converted to non-retryable errors:

```csharp theme={null}
Handler.Run(task => {
    // If this throws, it becomes Error(exception.Message)
    var required = task.task_data["required"];
    return new Success(new { value = required });
});
```

For explicit error handling:

```csharp theme={null}
Handler.Run(task => {
    if (!task.task_data.ContainsKey("required"))
        return new Error("Missing required field");
    
    try {
        var result = ExternalApiCall();
        return new Success(result);
    } catch (HttpRequestException e) {
        return new Error($"API unavailable: {e.Message}", retryable: true);
    }
});
```

## Async Handlers

```csharp theme={null}
using TaskDaemon;

await Handler.RunAsync(async task => {
    var url = task.task_data["url"]?.ToString();
    
    using var client = new HttpClient();
    var response = await client.GetStringAsync(url);
    
    return new Success(new { data = response });
});
```

## Dockerfile

```dockerfile theme={null}
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS builder
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/runtime:8.0
WORKDIR /app
COPY --from=builder /app/out ./
CMD ["dotnet", "Handler.dll"]
```

For a self-contained single-file deployment:

```dockerfile theme={null}
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS builder
WORKDIR /app
COPY . ./
RUN dotnet publish -c Release -r linux-x64 --self-contained true -p:PublishSingleFile=true -o out

FROM mcr.microsoft.com/dotnet/runtime-deps:8.0
COPY --from=builder /app/out/Handler /handler
CMD ["/handler"]
```

## Handler Configuration

```toml theme={null}
[handlers.process]
image = "csharp-handler:latest"
instances = 4
timeout = 30
```

## Requirements

* .NET 6.0+ (uses records and file-scoped namespaces)
* System.Text.Json for serialization (built-in)
