A .NET client library for TinyURL services
$ dotnet add package HLab.TinyURL.ClientA .NET 8 client library for TinyURL services that allows you to create shortened URLs programmatically using the official TinyURL API.
This library provides two client classes to fit different use cases:
⭐ Recommendation: We highly recommend using
TinyURLClientfor all new projects as it provides comprehensive API access, better error handling, and future-proof functionality.
Best for: All applications - from simple URL shortening to enterprise analytics.
Best for: Legacy applications or minimal feature requirements.
Install the package via NuGet:
dotnet add package HLab.TinyURL.Client
TinyURL API supports two authentication methods for accessing premium features and analytics:
Use Bearer token in the Authorization header for secure API access:
using HLab.TinyURL.Client;
// Configure HttpClient with Bearer token
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "your-bearer-token");
var client = new TinyURLClient(httpClient);
// Or using HttpClientFactory (recommended for production)
builder.Services.AddHttpClient("TinyUrlClient", client =>
{
client.BaseAddress = new Uri("https://api.tinyurl.com");
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "your-bearer-token");
});
HTTP Header Format:
Authorization: Bearer your-bearer-token-here
Pass the API key as a URL parameter for simple authentication:
using HLab.TinyURL.Client;
// Configure base URL with API token parameter
var httpClient = new HttpClient();
var client = new TinyURLClient("https://api.tinyurl.com?api_token=your-api-key", httpClient);
// Or using HttpClientFactory
builder.Services.AddHttpClient("TinyUrlClient", client =>
{
client.BaseAddress = new Uri("https://api.tinyurl.com?api_token=your-api-key");
});
URL Format:
https://api.tinyurl.com/create?api_token=your-api-key-here
| Method | Security | Use Case | Implementation |
|---|---|---|---|
| Bearer Token | ✅ Higher (Header-based) | Production apps, Enterprise | Authorization: Bearer token |
| API Key | ⚠️ Standard (URL parameter) | Simple integrations, Testing | ?api_token=key |
Store your credentials securely using environment variables:
// Using Bearer Token from environment
var bearerToken = Environment.GetEnvironmentVariable("TINYURL_BEARER_TOKEN");
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", bearerToken);
// Using API Key from environment
var apiKey = Environment.GetEnvironmentVariable("TINYURL_API_KEY");
var baseUrl = $"https://api.tinyurl.com?api_token={apiKey}";
var client = new TinyURLClient(baseUrl, httpClient);
// Or in appsettings.json
{
"TinyUrl": {
"BearerToken": "your-bearer-token",
"ApiKey": "your-api-key"
}
}
For basic URL shortening without analytics, you can use the library without authentication:
// No authentication - limited to basic features
var client = new TinyUrlSimpleClient();
var shortUrl = await client.CreateShortUrlAsync("https://example.com");
⚠️ Note: Authentication is required for analytics, bulk operations, custom domains, and other advanced TinyURL features.
using HLab.TinyURL.Client;
// ✅ BEST PRACTICE: Use HttpClientFactory (in DI container)
public class UrlShorteningService
{
private readonly IHttpClientFactory _httpClientFactory;
public UrlShorteningService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<string> ShortenAsync(string url)
{
using var httpClient = _httpClientFactory.CreateClient();
var client = new TinyURLClient(httpClient);
var result = await client.CreateTinyUrlAsync(new CreateTinyURLRequest
{
Url = url
});
return result.Data.Tiny_url;
}
}
// Alternative for console apps (not recommended for production)
var httpClient = new HttpClient(); // ⚠️ Consider using HttpClientFactory instead
var client = new TinyURLClient(httpClient);
try
{
var result = await client.CreateTinyUrlAsync(new CreateTinyURLRequest
{
Url = "https://www.example.com"
});
Console.WriteLine($"Shortened URL: {result.Data.Tiny_url}");
}
finally
{
client.Dispose();
httpClient.Dispose();
}
For minimal feature requirements, you can use the legacy simple client:
using HLab.TinyURL.Client;
// Legacy simple client
var client = new TinyUrlSimpleClient();
try
{
string shortUrl = await client.CreateShortUrlAsync("https://www.example.com");
Console.WriteLine($"Shortened URL: {shortUrl}");
}
finally
{
client.Dispose();
}
using HLab.TinyURL.Client;
var httpClient = new HttpClient();
var client = new TinyURLClient(httpClient);
try
{
// Shorten a URL with custom alias using TinyURLClient
var result = await client.CreateTinyUrlAsync(new CreateTinyURLRequest
{
Url = "https://www.example.com",
Alias = "my-custom-alias"
});
Console.WriteLine($"Custom shortened URL: {result.Data.Tiny_url}");
}
catch (ArgumentException ex)
{
Console.WriteLine($"Invalid alias: {ex.Message}");
}
catch (TinyUrlException ex)
{
Console.WriteLine($"TinyURL error: {ex.Message}");
}
finally
{
client.Dispose();
}
For applications requiring analytics and advanced features:
using HLab.TinyURL.Client;
// ✅ PRODUCTION APPROACH: Using HttpClientFactory in a service
public class TinyUrlAnalyticsService
{
private readonly IHttpClientFactory _httpClientFactory;
public TinyUrlAnalyticsService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<(string Url, int Clicks)> CreateAndTrackAsync(string url, string alias)
{
using var httpClient = _httpClientFactory.CreateClient("TinyUrlAnalytics");
var client = new TinyURLClient(httpClient);
// Create shortened URL with advanced options
var createRequest = new CreateTinyURLRequest
{
Url = url,
Alias = alias,
Tags = new[] { "marketing", "campaign-2024" }
};
var response = await client.CreateTinyUrlAsync(createRequest);
// Get analytics for the URL
var analytics = await client.GeneralAnalyticsAsync(
from: DateTime.Now.AddDays(-30).ToString("yyyy-MM-dd"),
to: DateTime.Now.ToString("yyyy-MM-dd"),
alias: alias,
tag: null
);
return (response.Data.Tiny_url, analytics.Data.Total);
}
}
// Configure HttpClient with authentication in Program.cs
// See Authentication section above for details on Bearer token vs API key
builder.Services.AddHttpClient("TinyUrlAnalytics", client =>
{
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "your-bearer-token");
client.BaseAddress = new Uri("https://api.tinyurl.com");
});
using HLab.TinyURL.Client;
var client = new TinyUrlSimpleClient();
var options = new TinyUrlOptions
{
Url = "https://www.example.com",
Alias = "my-alias"
};
try
{
string shortUrl = await client.CreateShortUrlAsync(options);
Console.WriteLine($"Shortened URL: {shortUrl}");
}
catch (TinyUrlException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
client.Dispose();
}
// TinyURLClient (Recommended) - Comprehensive features
services.AddHttpClient<TinyURLClient>((serviceProvider, httpClient) =>
{
// Configure API authentication (see Authentication section for details)
httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "your-bearer-token");
httpClient.BaseAddress = new Uri("https://api.tinyurl.com");
});
// Or register as scoped service
services.AddScoped<TinyURLClient>(provider =>
{
var httpClientFactory = provider.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient();
return new TinyURLClient(httpClient);
});
// Alternative: Simple client for legacy applications
services.AddHttpClient<TinyUrlSimpleClient>();
// Or configure simple client manually
services.AddSingleton<TinyUrlSimpleClient>(provider =>
{
var httpClient = provider.GetRequiredService<HttpClient>();
return new TinyUrlSimpleClient(httpClient);
});
The comprehensive client should be configured using HttpClientFactory for production applications:
// ✅ RECOMMENDED: Configure using HttpClientFactory
// In Program.cs or Startup.cs
builder.Services.AddHttpClient<TinyURLClient>("TinyUrlClient", client =>
{
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "your-bearer-token");
client.BaseAddress = new Uri("https://api.tinyurl.com");
client.Timeout = TimeSpan.FromSeconds(30);
});
// Usage in your service
public class MyService
{
private readonly IHttpClientFactory _httpClientFactory;
public MyService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<string> CreateUrlAsync(string url)
{
using var httpClient = _httpClientFactory.CreateClient("TinyUrlClient");
var client = new TinyURLClient(httpClient);
var result = await client.CreateTinyUrlAsync(new CreateTinyURLRequest { Url = url });
return result.Data.Tiny_url;
}
}
// ⚠️ For console apps only (not recommended for production)
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "your-bearer-token");
var client = new TinyURLClient(httpClient);
The simple client supports configuration through the Options pattern:
var options = new TinyUrlOptions
{
BaseUrl = "https://api.tinyurl.com",
Timeout = TimeSpan.FromSeconds(30),
RetryCount = 3,
ValidateSsl = true
};
var client = new TinyUrlSimpleClient(httpClient, options);
// ✅ BEST: HttpClientFactory in DI container
public async Task<string> RecommendedApproach(IHttpClientFactory factory)
{
using var httpClient = factory.CreateClient("TinyUrlClient");
using var client = new TinyURLClient(httpClient);
var result = await client.CreateTinyUrlAsync(new CreateTinyURLRequest
{
Url = "https://www.example.com"
});
return result.Data.Tiny_url;
}
// ⚠️ ACCEPTABLE: For simple console apps only
using var httpClient = new HttpClient(); // Consider HttpClientFactory for production
using var client = new TinyURLClient(httpClient);
var result = await client.CreateTinyUrlAsync(new CreateTinyURLRequest
{
Url = "https://www.example.com"
});
Console.WriteLine($"Shortened URL: {result.Data.Tiny_url}");
Always use IHttpClientFactory instead of creating HttpClient instances directly to avoid common issues:
HttpClient creation can exhaust available sockets// ✅ RECOMMENDED: Using HttpClientFactory
public class TinyUrlService
{
private readonly IHttpClientFactory _httpClientFactory;
public TinyUrlService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<string> ShortenUrlAsync(string url)
{
// Create HttpClient from factory
using var httpClient = _httpClientFactory.CreateClient("TinyUrlClient");
var client = new TinyURLClient(httpClient);
var result = await client.CreateTinyUrlAsync(new CreateTinyURLRequest { Url = url });
return result.Data.Tiny_url;
}
}
// Configure in Program.cs or Startup.cs
builder.Services.AddHttpClient("TinyUrlClient", client =>
{
client.BaseAddress = new Uri("https://api.tinyurl.com");
client.Timeout = TimeSpan.FromSeconds(30);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "your-bearer-token");
});
// ❌ AVOID: Creating HttpClient directly
public async Task<string> BadExample()
{
using var httpClient = new HttpClient(); // This can cause socket exhaustion!
var client = new TinyURLClient(httpClient);
// ... rest of code
}
// ❌ AVOID: Singleton HttpClient without proper lifecycle management
private static readonly HttpClient _httpClient = new HttpClient(); // Memory leaks!
// Configure with retry policies, timeouts, and custom handlers
builder.Services.AddHttpClient<TinyURLClient>("TinyUrlClient")
.ConfigureHttpClient(client =>
{
client.BaseAddress = new Uri("https://api.tinyurl.com");
client.Timeout = TimeSpan.FromSeconds(30);
})
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy());
// Named client registration for TinyURLClient
builder.Services.AddTransient<ITinyUrlService>(provider =>
{
var httpClientFactory = provider.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient("TinyUrlClient");
return new TinyURLClient(httpClient);
});
Both clients provide comprehensive error handling:
try
{
string shortUrl = await client.CreateShortUrlAsync("https://www.example.com");
Console.WriteLine($"Success: {shortUrl}");
}
catch (TinyUrlException ex)
{
Console.WriteLine($"TinyURL API Error: {ex.Message}");
Console.WriteLine($"Error Code: {ex.ErrorCode}");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Network Error: {ex.Message}");
}
catch (TaskCanceledException ex)
{
Console.WriteLine($"Timeout Error: {ex.Message}");
}
A comprehensive API client that provides full access to TinyURL's API features including analytics and advanced operations.
⭐ This is the recommended client for all new projects.
A comprehensive API client that provides full access to TinyURL's API features including analytics and advanced operations.
TinyURLClient(HttpClient httpClient) - Creates instance with provided HttpClientAnalytics Methods:
RawLogsAnalyticsAsync() - Get raw analytics logsTimelineAnalyticsAsync() - Get timeline-based analyticsGeneralAnalyticsAsync() - Get browser, OS, and device analyticsWeekdaysPopularityAnalyticsAsync() - Get weekday popularity dataHourPopularityAnalyticsAsync() - Get hourly popularity dataTopSourcesAnalyticsAsync() - Get top traffic sourcesTopLanguagesAnalyticsAsync() - Get top languages analyticsLocationAnalyticsAsync() - Get geographic analyticsURL Management Methods:
CreateTinyUrlAsync() - Create shortened URLsUpdateTinyUrlAsync() - Update existing URLsChangeTinyUrlDomainAsync() - Change URL domainArchiveTinyUrlAsync() / UnarchiveTinyUrlAsync() - Archive managementDomain & Alias Methods:
CreateAliasAsync() - Create custom aliasesGetDomainsAsync() - Get available domainsGetTinyUrlsByDomainAsync() - Get URLs by domainAll methods support cancellation tokens and follow async/await patterns.
A simple, lightweight client for basic URL shortening operations. Consider using TinyURLClient instead for better features and future compatibility.
CreateShortUrlAsync(string url, string? alias = null, CancellationToken cancellationToken = default)CreateShortUrlAsync(TinyUrlOptions options, CancellationToken cancellationToken = default)TinyUrlSimpleClient() - Creates a new instance with internal HttpClientTinyUrlSimpleClient(HttpClient httpClient) - Creates a new instance with provided HttpClientProperties:
Url (required) - The URL to shortenAlias (optional) - Custom alias (5-30 characters, alphanumeric, hyphens, underscores only)Custom exception thrown when TinyURL API operations fail.
Custom aliases must follow these rules:
The library provides comprehensive error handling:
ArgumentNullException - When URL is null or emptyArgumentException - When URL format is invalid or alias doesn't meet requirementsTinyUrlException - When TinyURL service returns an errorHttpRequestException - When HTTP communication failsThe library includes comprehensive unit tests using xUnit, Moq, and Shouldly:
# Run all tests
dotnet test
# Run tests with detailed output
dotnet test --verbosity normal
# Run tests with coverage
dotnet test --collect:"XPlat Code Coverage"
// Example unit test using Moq
[Fact]
public async Task CreateShortUrlAsync_ShouldReturnShortUrl_WhenValidUrl()
{
// Arrange
var mockHttpClient = new Mock<HttpClient>();
var client = new TinyUrlSimpleClient(mockHttpClient.Object);
// Act & Assert
var result = await client.CreateShortUrlAsync("https://www.example.com");
result.ShouldNotBeNullOrEmpty();
}
This repository includes comprehensive VS Code debugging configurations for the console application example.
Open in VS Code:
code .
Debug the Console App:
F5 and select "Debug TinyURL Console App"| Configuration | Description | Use Case |
|---|---|---|
| Debug TinyURL Console App | Full debugging with breakpoints | Development and troubleshooting |
| Debug TinyURL Console App (External Terminal) | Debug in external terminal | Better terminal interaction |
| Run TinyURL Console App (No Debug) | Run without debugger | Performance testing |
Access via Ctrl+Shift+P → Tasks: Run Task:
Development Tasks:
build-console-app - Build the console application (Debug mode)build-main-library - Build the main TinyURL library (Debug mode)run-console-app - Run the console applicationRelease & Packaging:
build-library-release - Build library in Release modepack-nuget-release - Create NuGet package in Release modebuild-and-pack-release - 🚀 Build and pack Release (recommended)Maintenance:
clean-all - Clean build outputsclean-artifacts - Clean artifacts directoryUseful Breakpoints:
Program.csProgram.csProgram.csProgram.csVariables to Watch:
bearerToken / apiKey - Authentication credentialscreateRequest - Request object sent to APIresponse.Data - API response data structureConsole Integration:
TinyURL-nuget/
├── .vscode/
│ ├── launch.json # Debug configurations
│ ├── tasks.json # Build and run tasks
│ ├── settings.json # VS Code workspace settings
│ └── extensions.json # Recommended extensions
├── artifacts/ # 📦 Generated NuGet packages (Release builds)
│ └── HLab.TinyURL.Client.x.x.x.nupkg
├── examples/ConsoleApp/TinyUrlConsoleExample/
│ ├── Program.cs # 🎯 Main debugging target
│ ├── .vscode/ # Console app specific configs
│ └── DEBUG_GUIDE.md # Detailed debugging guide
└── src/HLab.TinyURL.Client/ # Main library source
The workspace will recommend installing:
ms-dotnettools.csdevkit)ms-dotnettools.csharp)ms-dotnettools.vscode-dotnet-runtime)This project includes two console application examples:
The examples/ConsoleApp/TinyUrlConsoleExample/ demonstrates:
See examples/ConsoleApp/TinyUrlConsoleExample/README.md for detailed documentation.
The examples/ConsoleApp/TinyUrlSimpleExample/ demonstrates:
See examples/ConsoleApp/TinyUrlSimpleExample/README.md for detailed documentation.
Run the Examples:
# Full-featured example (with authentication and analytics)
cd examples/ConsoleApp/TinyUrlConsoleExample
dotnet run
# Simple example (no authentication required)
cd examples/ConsoleApp/TinyUrlSimpleExample
dotnet run
This project is licensed under the MIT License.
Contributions are welcome! Please feel free to submit a Pull Request.