Package Description
$ dotnet add package InfinityFlow.DigitalOcean.ClientA strongly-typed .NET client for the DigitalOcean API, generated using Microsoft's Kiota SDK generator. This client provides a simple and intuitive way to interact with DigitalOcean's services from .NET applications.
graph TD
A[Client Application] -->|Uses| B[DigitalOceanClient]
B -->|Authenticates via| C[ITokenProvider]
C -->|Implements| D[StaticTokenProvider]
C -->|Can implement| E[Custom Token Provider]
B -->|Makes requests to| F[DigitalOcean API]
B -->|Uses| G[Strongly-typed Models]
G -->|Includes| H[Account, Droplet, etc.]
Install the package from NuGet:
dotnet add package InfinityFlow.DigitalOcean.Client// Create a client with an API token
var tokenProvider = new StaticTokenProvider("your-digitalocean-api-token");
var httpClient = new HttpClient();
var client = new DigitalOceanClient(httpClient, tokenProvider);
// Get account information
var account = await client.Account.GetAsync();
Console.WriteLine($"Account: {account.Email}, {account.Status}");
// List all droplets
var droplets = await client.Droplets.GetAsync();
foreach (var droplet in droplets.Droplets)
{
Console.WriteLine($"Droplet: {droplet.Name}, {droplet.Status}");
}// In Program.cs or Startup.cs
services.AddDigitalOceanClient(options =>
{
options.Token = Configuration["DigitalOcean:ApiToken"];
});
// In your service
public class MyService
{
private readonly DigitalOceanClient _client;
public MyService(DigitalOceanClient client)
{
_client = client;
}
public async Task DoSomethingAsync()
{
var droplets = await _client.Droplets.GetAsync();
// ...
}
}This client covers all DigitalOcean API endpoints:
The client supports authentication using a DigitalOcean API token:
// Static token provider (simple approach)
var tokenProvider = new StaticTokenProvider("your-api-token");
// For more dynamic scenarios, implement ITokenProvider
public class MyTokenProvider : ITokenProvider
{
public Task<string> GetTokenAsync(CancellationToken cancellationToken)
{
// Get token from a secure storage or service
return Task.FromResult(GetSecureToken());
}
}You can customize requests with options:
// Get droplets with paging
var options = new DropletsRequestBuilder.GetRequestConfiguration
{
QueryParameters = new DropletsRequestBuilder.GetQueryParameters
{
Page = 2,
PerPage = 25
}
};
var droplets = await client.Droplets.GetAsync(requestConfiguration: options);The client throws strongly-typed exceptions for API errors:
try
{
var droplet = await client.Droplets.ByDropletId(123456).GetAsync();
// Process droplet
}
catch (DigitalOceanApiException ex) when (ex.StatusCode == 404)
{
Console.WriteLine("Droplet not found");
}
catch (DigitalOceanApiException ex)
{
Console.WriteLine($"API error: {ex.StatusCode}, {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}");
}Creating resources is type-safe and intuitive:
// Create a new droplet
var newDroplet = new Droplet
{
Name = "example-droplet",
Region = "nyc3",
Size = "s-1vcpu-1gb",
Image = 123456789, // Ubuntu image ID
SshKeys = new List<int> { 123456 }, // SSH key ID
Backups = false,
Ipv6 = true,
Monitoring = true,
Tags = new List<string> { "web", "production" }
};
var createdDroplet = await client.Droplets.PostAsync(newDroplet);
Console.WriteLine($"Created droplet with ID: {createdDroplet.Id}");The client includes strongly-typed models for all DigitalOcean entities. Here are some key models:
// Account information
public class Account
{
public string Email { get; set; }
public string Status { get; set; }
public Account_status Status_enum { get; set; }
public bool Droplet_limit { get; set; }
public bool Email_verified { get; set; }
public Account_team Team { get; set; }
public DateTimeOffset Created_at { get; set; }
}
// Droplet configuration
public class Droplet
{
public int Id { get; set; }
public string Name { get; set; }
public int Memory { get; set; }
public int Vcpus { get; set; }
public int Disk { get; set; }
public string Region { get; set; }
public string Size { get; set; }
public string Status { get; set; }
// Additional properties...
}
// Many other models available...git clone https://github.com/InfinityFlowApp/InfinityFlow.DigitalOcean.Client.git
cd InfinityFlow.DigitalOcean.Client
dotnet builddotnet testThe client is generated using Kiota:
# Install Kiota
dotnet tool install -g Microsoft.OpenAPI.Kiota
# Get the OpenAPI specification
curl -o openapi.json https://raw.githubusercontent.com/digitalocean/openapi/master/specification/DigitalOcean-public.v2.yaml
# Generate the client
kiota generate --language CSharp --namespace InfinityFlow.DigitalOcean.Client --output-dir ./src/InfinityFlow.DigitalOcean.Client --openapi openapi.json --class-name DigitalOceanClient --clean-outputWe welcome contributions! Please feel free to submit a Pull Request.
git checkout -b my-new-feature)git commit -am 'Add some feature')git push origin my-new-feature)This project is licensed under the MIT License - see the LICENSE file for details.
| Issue | Solution |
|---|---|
| 401 Unauthorized | Verify your API token is valid and has the required scopes |
| 429 Too Many Requests | Implement rate limiting or exponential backoff in your application |
| Connection timeout | Check your network connection and DigitalOcean status page |
| Serialization errors | Ensure you're using the latest client version compatible with the API |
Enable detailed logging by configuring your logger:
// Setup logging (using Microsoft.Extensions.Logging)
services.AddLogging(builder =>
{
builder.AddConsole();
builder.AddDebug();
builder.SetMinimumLevel(LogLevel.Debug);
});
// Add client with logging
services.AddDigitalOceanClient(options =>
{
options.Token = Configuration["DigitalOcean:ApiToken"];
options.EnableDebugLogging = true;
});The DigitalOcean API implements rate limiting. You can handle this by checking response headers:
try
{
var result = await client.Droplets.GetAsync();
// Process result
}
catch (DigitalOceanApiException ex) when (ex.StatusCode == 429)
{
// Get rate limit headers
var rateLimit = ex.ResponseHeaders.GetValueOrDefault("RateLimit-Limit");
var rateLimitRemaining = ex.ResponseHeaders.GetValueOrDefault("RateLimit-Remaining");
var rateLimitReset = ex.ResponseHeaders.GetValueOrDefault("RateLimit-Reset");
// Implement backoff strategy
var resetTime = DateTimeOffset.FromUnixTimeSeconds(long.Parse(rateLimitReset));
var waitTime = resetTime - DateTimeOffset.UtcNow;
Console.WriteLine($"Rate limited. Waiting for {waitTime.TotalSeconds} seconds before retrying.");
await Task.Delay(waitTime);
// Retry the request
result = await client.Droplets.GetAsync();
}