CurlDotNet Tutorial Implementations

Every tutorial below is a direct lift from the dev.to skyscraper article and now includes runnable C# code. Install CurlDotNet before trying them:

dotnet add package CurlDotNet

All projects target .NET 8/10.

Tutorial 1: Self-Service API Explorer

Why it matters: Build an ASP.NET Core explorer so C# developers can store and execute CurlDotNet commands without leaving .NET tooling.

Create an ASP.NET Core Minimal API that lets engineers run curated CurlDotNet templates.

// NuGet: https://www.nuget.org/packages/CurlDotNet/
using CurlDotNet;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ApiExplorerStore>();
var app = builder.Build();

app.MapPost("/requests", async (ApiExplorerStore store, RequestTemplate template) =>
{
    store.Add(template);
    return Results.Created($"/requests/{template.Id}", template);
});

app.MapGet("/requests/{id}", (ApiExplorerStore store, Guid id)
    => store.TryGet(id, out var template) ? Results.Ok(template) : Results.NotFound());

app.MapPost("/requests/{id}/execute", async (ApiExplorerStore store, Guid id) =>
{
    if (!store.TryGet(id, out var template))
    {
        return Results.NotFound();
    }

    var result = await Curl.ExecuteAsync(template.Command);
    store.LogExecution(id, result);
    return Results.Json(new { result.StatusCode, result.Body });
});

app.Run();

public sealed record RequestTemplate(Guid Id, string Name, string Command, string Description);

public sealed class ApiExplorerStore
{
    private readonly Dictionary<Guid, RequestTemplate> _templates = new();
    private readonly List<string> _logs = new();

    public void Add(RequestTemplate template) => _templates[template.Id] = template;
    public bool TryGet(Guid id, out RequestTemplate template) => _templates.TryGetValue(id, out template!);
    public void LogExecution(Guid id, CurlResult result)
        => _logs.Add($"{DateTimeOffset.UtcNow:o}|{id}|{result.StatusCode}");
}

Tutorial 2: Disaster Recovery Runbook CLI

Why it matters: Wrap disaster-recovery curl workflows in a System.CommandLine CLI so operations teams run them from managed C# code.

Package critical workflows inside a System.CommandLine app so operators can execute recovery steps safely.

// NuGet: https://www.nuget.org/packages/CurlDotNet/
using System.CommandLine;
using CurlDotNet;

var environmentOption = new Option<string>("--environment", () => "production");
var dryRunOption = new Option<bool>("--dry-run", () => false);
var runbook = new RootCommand("DR runbook powered by CurlDotNet");

runbook.SetHandler(async (string environment, bool dryRun) =>
{
    var command = $"curl https://{environment}.example.com/api/restore -X POST";
    if (dryRun)
    {
        Console.WriteLine($"Would execute: {command}");
        return;
    }

    var result = await Curl.ExecuteAsync(command);
    Console.WriteLine($"Restore status {result.StatusCode}");
}, environmentOption, dryRunOption);

await runbook.InvokeAsync(args);

Tutorial 3: Compliance Evidence Generator

Why it matters: Generate evidence bundles inside .NET by executing CurlDotNet commands and persisting their responses for auditors.

Generate immutable bundles proving regulated workflows were run through CurlDotNet.

// NuGet: https://www.nuget.org/packages/CurlDotNet/
using System.Text.Json;
using CurlDotNet;

var evidence = new EvidenceGenerator("evidence");
await evidence.RunAsync("delete-user", "curl -X DELETE https://api.example.com/users/42");

public sealed class EvidenceGenerator
{
    private readonly string _directory;

    public EvidenceGenerator(string directory)
    {
        Directory.CreateDirectory(directory);
        _directory = directory;
    }

    public async Task RunAsync(string workflow, string command)
    {
        var result = await Curl.ExecuteAsync(command);
        var bundle = new
        {
            Workflow = workflow,
            Timestamp = DateTimeOffset.UtcNow,
            result.StatusCode,
            result.Headers,
            result.Body
        };

        var path = Path.Combine(_directory, $"{workflow}-{DateTimeOffset.UtcNow:yyyyMMddHHmmss}.json");
        await File.WriteAllTextAsync(path, JsonSerializer.Serialize(bundle, new JsonSerializerOptions { WriteIndented = true }));
    }
}

Tutorial 4: Migrating Bash Scripts to CurlDotNet

Why it matters: Port legacy bash scripts to a modern C# console app that calls CurlDotNet instead of shelling out to curl.

Wrap legacy curl calls in a single C# console application.

// NuGet: https://www.nuget.org/packages/CurlDotNet/
using CurlDotNet;

string[] commands =
[
    "curl https://api.legacy.com/login -d 'user=svc&password=secret'",
    "curl https://api.legacy.com/data -H 'Accept: application/json'",
    "curl https://api.legacy.com/logout"
];

foreach (var command in commands)
{
    var result = await Curl.ExecuteAsync(command);
    Console.WriteLine($"{command} => {result.StatusCode}");
}

Tutorial 5: Full-Fidelity Mock Server

Why it matters: Host a realistic mock API in ASP.NET Core and exercise it with CurlDotNet to keep integration tests all within .NET.

Use ASP.NET Core to emulate partner APIs while verifying behavior with CurlDotNet.

// NuGet: https://www.nuget.org/packages/CurlDotNet/
using CurlDotNet;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/orders", () => Results.Json(new { items = new[] { new { id = 1, total = 99 } } }));
app.MapPost("/orders", (Order payload) => Results.Created($"/orders/{payload.Id}", payload));

await app.StartAsync();
var listResult = await Curl.ExecuteAsync("curl http://localhost:5000/orders");
Console.WriteLine(listResult.Body);
await app.StopAsync();

public sealed record Order(int Id, decimal Total);

Tutorial 6: CurlDotNet + Message Buses

Why it matters: Publish CurlDotNet outcomes to Service Bus so distributed .NET systems can react to curl-like activity.

Publish events whenever CurlDotNet completes a request.

// NuGet: https://www.nuget.org/packages/CurlDotNet/
using System.Text.Json;
using CurlDotNet;
using Azure.Messaging.ServiceBus;

var connectionString = Environment.GetEnvironmentVariable("SERVICEBUS")
    ?? throw new InvalidOperationException("SERVICEBUS connection string missing");
var client = new ServiceBusClient(connectionString);
var sender = client.CreateSender("curl-events");

var result = await Curl.ExecuteAsync("curl https://api.example.com/payments");
var message = new ServiceBusMessage(JsonSerializer.Serialize(new
{
    Command = "payments",
    result.StatusCode,
    Timestamp = DateTimeOffset.UtcNow
}));
await sender.SendMessageAsync(message);

Tutorial 7: Observability-First Mobile Backend

Why it matters: Expose a mobile-friendly backend endpoint that enriches CurlDotNet calls with device metadata, keeping the entire flow in C#.

Backend service that enriches CurlDotNet calls with mobile metadata.

// NuGet: https://www.nuget.org/packages/CurlDotNet/
using CurlDotNet;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapPost("/mobile/proxy", async (MobileRequest request) =>
{
    var command = $"curl {request.UpstreamUrl} -H 'X-App-Version: {request.AppVersion}' -H 'X-Platform: {request.Platform}'";
    var result = await Curl.ExecuteAsync(command);
    return Results.Json(new { result.StatusCode, result.Body });
});

app.Run();

public sealed record MobileRequest(string UpstreamUrl, string AppVersion, string Platform);

Tutorial 8: Multi-Cloud Disaster Recovery Bridge

Why it matters: Deploy CurlDotNet bridges across clouds using lightweight C# workers so failover scripts never rely on ad-hoc curl binaries.

Deploy the same bridge in multiple clouds; configuration shown here for a console worker.

// NuGet: https://www.nuget.org/packages/CurlDotNet/
using CurlDotNet;

var targets = new[]
{
    "curl https://azure-region.example.com/bridge",
    "curl https://aws-region.example.com/bridge"
};

foreach (var target in targets)
{
    var response = await Curl.ExecuteAsync(target);
    Console.WriteLine($"{target} => {response.StatusCode}");
}

Tutorial 9: Streaming Analytics Pipeline

Why it matters: Ingest streaming responses through CurlDotNet and channel them via modern C# concurrency primitives for analytics.

Read server-sent events and push them into System.Threading.Channels.

// NuGet: https://www.nuget.org/packages/CurlDotNet/
using System.Threading.Channels;
using CurlDotNet;

var channel = Channel.CreateUnbounded<string>();
var streamingTask = Task.Run(async () =>
{
    var result = await Curl.ExecuteAsync("curl https://stream.example.com/logs");
    foreach (var line in result.Body.Split('\n', StringSplitOptions.RemoveEmptyEntries))
    {
        await channel.Writer.WriteAsync(line);
    }
    channel.Writer.Complete();
});

await foreach (var line in channel.Reader.ReadAllAsync())
{
    Console.WriteLine(line);
}

await streamingTask;

Tutorial 10: Customer Support Troubleshooting Toolkit

Why it matters: Give support agents a safe C# console that runs approved CurlDotNet commands rather than raw curl on their laptops.

Build a trimmed-down desktop console that executes pre-approved CurlDotNet commands.

// NuGet: https://www.nuget.org/packages/CurlDotNet/
using System.Text.Json;
using CurlDotNet;

var recipes = new Dictionary<int, string>
{
    [1] = "curl https://api.example.com/accounts/lookup?email=support@example.com",
    [2] = "curl https://api.example.com/orders/latest"
};

Console.WriteLine("Select action: 1) Lookup account 2) Latest order");
var choice = int.Parse(Console.ReadLine() ?? "1");
var command = recipes[choice];
var result = await Curl.ExecuteAsync(command);
Console.WriteLine(JsonSerializer.Serialize(new { result.StatusCode, result.Body }, new JsonSerializerOptions { WriteIndented = true }));

About This Documentation

💎 Sponsored by IronSoftware - Enterprise .NET components trusted by thousands of developers worldwide.

✍️ Written by Jacob Mellor, CTO at IronSoftware.

📦 Get CurlDotNet: NuGet Package | GitHub Repository