Skip to content

jyswee/oddsockets-csharp-sdk

Repository files navigation

OddSockets .NET SDK

NuGet Version .NET License: MIT

Official .NET SDK for OddSockets - Enterprise-ready real-time messaging with automatic load balancing and failover.

Features

  • Real-time messaging with automatic load balancing
  • Task-based async/await patterns for modern .NET
  • 🔒 Strong typing with nullable reference types
  • 🏗️ Dependency injection support for ASP.NET Core
  • 📦 Bulk message publishing for high-throughput scenarios
  • 📚 Message history and presence tracking
  • 🔄 Automatic reconnection with exponential backoff
  • 🧵 Thread-safe operations
  • 📝 Comprehensive logging support
  • 🎯 Multi-targeting (.NET 6.0, .NET 8.0, .NET Standard 2.0)

Installation

Package Manager Console

Install-Package OddSockets.DotNet.SDK

.NET CLI

dotnet add package OddSockets.DotNet.SDK

PackageReference

<PackageReference Include="OddSockets.DotNet.SDK" Version="0.1.0-beta.1" />

Quick Start

Basic Usage

using OddSockets;
using OddSockets.Models;

// Create configuration
var config = new OddSocketsConfigBuilder()
    .WithApiKey("ak_live_your_api_key_here")
    .WithUserId("user123")
    .Build();

// Create client
using var client = new OddSocketsClient(config);

// Connect
await client.ConnectAsync();

// Get a channel
var channel = client.Channel("my-channel");

// Subscribe to messages
await channel.SubscribeAsync(message =>
{
    Console.WriteLine($"Received: {message.Data}");
});

// Publish a message
await channel.PublishAsync("Hello, OddSockets!");

ASP.NET Core Integration

// Program.cs or Startup.cs
builder.Services.AddSingleton<OddSocketsConfig>(provider =>
    new OddSocketsConfigBuilder()
        .WithApiKey(builder.Configuration["OddSockets:ApiKey"])
        .WithUserId("web-app-user")
        .Build());

builder.Services.AddSingleton<OddSocketsClient>();

// In your controller or service
public class ChatController : ControllerBase
{
    private readonly OddSocketsClient _oddSockets;

    public ChatController(OddSocketsClient oddSockets)
    {
        _oddSockets = oddSockets;
    }

    [HttpPost("send")]
    public async Task<IActionResult> SendMessage([FromBody] ChatMessage message)
    {
        var channel = _oddSockets.Channel("chat-room");
        var result = await channel.PublishAsync(message);
        return Ok(result);
    }
}

Configuration

Using Builder Pattern

var config = new OddSocketsConfigBuilder()
    .WithApiKey("ak_live_your_api_key_here")
    .WithManagerUrl("https://manager1.oddsockets.tyga.network") // Optional
    .WithUserId("user123") // Optional, auto-generated if not provided
    .WithAutoConnect(true) // Optional, default: true
    .WithReconnectAttempts(5) // Optional, default: 5
    .WithHeartbeatInterval(30) // Optional, default: 30 seconds
    .WithTimeout(10) // Optional, default: 10 seconds
    .Build();

Using Object Initializer

var config = new OddSocketsConfig
{
    ApiKey = "ak_live_your_api_key_here",
    UserId = "user123",
    AutoConnect = true,
    ReconnectAttempts = 3
};

Core Concepts

Client Management

using var client = new OddSocketsClient(config);

// Connection events
client.On(EventType.Connected, data => 
    Console.WriteLine("Connected!"));

client.On(EventType.Disconnected, data => 
    Console.WriteLine("Disconnected"));

client.On(EventType.Error, error => 
    Console.WriteLine($"Error: {error}"));

// Manual connection control
await client.ConnectAsync();
await client.DisconnectAsync();

// Check connection status
if (client.IsConnected)
{
    Console.WriteLine("Ready to send messages!");
}

Channel Operations

var channel = client.Channel("my-channel");

// Subscribe with options
await channel.SubscribeAsync(
    message => Console.WriteLine($"Message: {message.Data}"),
    SubscribeOptions.Builder()
        .WithPresence(true)
        .WithHistory(true)
        .WithFilter("important")
        .Build()
);

// Publish with options
var result = await channel.PublishAsync(
    "Hello World!",
    PublishOptions.Builder()
        .WithTtl(3600) // 1 hour
        .WithMetadata("priority", "high")
        .WithHistory(true)
        .Build()
);

Console.WriteLine($"Published: {result.MessageId}");

Bulk Publishing

var messages = new List<BulkMessage>
{
    new("channel1", "Message 1"),
    new("channel2", "Message 2"),
    new("channel3", new { type = "notification", text = "Message 3" })
};

var results = await client.PublishBulkAsync(messages);

foreach (var result in results)
{
    if (result.Success)
        Console.WriteLine($"✅ {result.Result?.MessageId}");
    else
        Console.WriteLine($"❌ {result.Error}");
}

Message History

var history = await channel.GetHistoryAsync(
    HistoryOptions.Builder()
        .WithLimit(50)
        .WithStart(DateTime.UtcNow.AddHours(-1))
        .WithReverse(true)
        .Build()
);

foreach (var message in history)
{
    Console.WriteLine($"{message.Timestamp}: {message.Data}");
}

Presence Tracking

// Enable presence when subscribing
await channel.SubscribeAsync(
    message => { /* handle message */ },
    SubscribeOptions.Builder().WithPresence(true).Build()
);

// Get current presence
var presence = await channel.GetPresenceAsync();
Console.WriteLine($"{presence.Count} users online:");
foreach (var user in presence.Users)
{
    Console.WriteLine($"- {user}");
}

// Listen for presence changes
channel.On(EventType.Presence, data =>
{
    Console.WriteLine($"Presence update: {data}");
});

Advanced Features

Error Handling

try
{
    await channel.PublishAsync("test message");
}
catch (OddSocketsConnectionException ex)
{
    Console.WriteLine($"Connection error: {ex.Message}");
    // Handle connection issues
}
catch (OddSocketsChannelException ex)
{
    Console.WriteLine($"Channel error: {ex.Message}");
    // Handle channel-specific issues
}
catch (OddSocketsException ex)
{
    Console.WriteLine($"General error: {ex.Message}");
    Console.WriteLine($"Error code: {ex.ErrorCode}");
    // Handle other OddSockets errors
}

Custom Logging

using Microsoft.Extensions.Logging;

var loggerFactory = LoggerFactory.Create(builder =>
    builder.AddConsole().SetMinimumLevel(LogLevel.Debug));

var logger = loggerFactory.CreateLogger<OddSocketsClient>();
var client = new OddSocketsClient(config, logger);

Dependency Injection with Logging

// Program.cs
builder.Services.AddLogging();
builder.Services.AddSingleton<OddSocketsConfig>(/* config */);
builder.Services.AddSingleton<OddSocketsClient>();

// Usage
public class MyService
{
    private readonly OddSocketsClient _client;
    private readonly ILogger<MyService> _logger;

    public MyService(OddSocketsClient client, ILogger<MyService> logger)
    {
        _client = client;
        _logger = logger;
    }

    public async Task SendNotificationAsync(string message)
    {
        try
        {
            var channel = _client.Channel("notifications");
            await channel.PublishAsync(message);
            _logger.LogInformation("Notification sent successfully");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to send notification");
            throw;
        }
    }
}

Examples

Real-time Chat Application

public class ChatService
{
    private readonly OddSocketsClient _client;
    private readonly OddSocketsChannel _channel;

    public ChatService(OddSocketsClient client)
    {
        _client = client;
        _channel = _client.Channel("chat-room");
    }

    public async Task StartAsync()
    {
        await _client.ConnectAsync();
        
        await _channel.SubscribeAsync(
            OnMessageReceived,
            SubscribeOptions.Builder()
                .WithPresence(true)
                .WithHistory(true)
                .Build()
        );
    }

    public async Task SendMessageAsync(string username, string message)
    {
        await _channel.PublishAsync(new
        {
            username,
            message,
            timestamp = DateTime.UtcNow
        });
    }

    private void OnMessageReceived(Message message)
    {
        // Handle incoming chat message
        Console.WriteLine($"Chat: {message.Data}");
    }
}

Live Dashboard Updates

public class DashboardService
{
    private readonly OddSocketsClient _client;

    public DashboardService(OddSocketsClient client)
    {
        _client = client;
    }

    public async Task PublishMetricsAsync(object metrics)
    {
        var channel = _client.Channel("dashboard-metrics");
        
        await channel.PublishAsync(metrics, 
            PublishOptions.Builder()
                .WithTtl(60) // Metrics expire after 1 minute
                .WithMetadata("type", "metrics")
                .Build()
        );
    }

    public async Task SubscribeToUpdatesAsync(Action<object> onUpdate)
    {
        var channel = _client.Channel("dashboard-metrics");
        
        await channel.SubscribeAsync(
            message => onUpdate(message.Data),
            SubscribeOptions.Builder()
                .WithFilter("metrics")
                .Build()
        );
    }
}

API Reference

OddSocketsClient

Method Description
ConnectAsync() Connect to OddSockets platform
DisconnectAsync() Disconnect from platform
Channel(string) Get or create a channel
PublishBulkAsync(IEnumerable<BulkMessage>) Publish multiple messages
On(EventType, Func<object?, Task>) Add event handler
Off(EventType, Func<object?, Task>?) Remove event handler

OddSocketsChannel

Method Description
SubscribeAsync(Func<Message, Task>, SubscribeOptions?) Subscribe to messages
UnsubscribeAsync() Unsubscribe from messages
PublishAsync(object?, PublishOptions?) Publish a message
GetHistoryAsync(HistoryOptions?) Get message history
GetPresenceAsync() Get presence information

Configuration Options

Property Type Default Description
ApiKey string Required Your OddSockets API key
ManagerUrl string https://manager1.oddsockets.tyga.network Manager service URL
UserId string? Auto-generated User identifier
AutoConnect bool true Auto-connect on creation
ReconnectAttempts int 5 Max reconnection attempts
HeartbeatInterval int 30 Heartbeat interval (seconds)
Timeout int 10 Request timeout (seconds)

Error Handling

The SDK provides specific exception types for different error scenarios:

  • OddSocketsException - Base exception for all SDK errors
  • OddSocketsConnectionException - Connection-related errors
  • OddSocketsAuthenticationException - Authentication failures
  • OddSocketsChannelException - Channel operation errors
  • OddSocketsMessageException - Message publishing errors

Thread Safety

The OddSockets .NET SDK is designed to be thread-safe:

  • Multiple threads can safely call methods on the same client instance
  • Channel operations are protected by internal synchronization
  • Event handlers are invoked safely across threads
  • Concurrent publish operations are supported

Performance Considerations

  • Use bulk publishing for high-throughput scenarios
  • Configure appropriate TTL values for messages
  • Consider message filtering to reduce client-side processing
  • Use presence tracking judiciously (only when needed)
  • Implement proper connection pooling in web applications

Compatibility

  • .NET 6.0 and later
  • .NET 8.0 and later
  • .NET Standard 2.0 (for .NET Framework 4.6.1+)
  • ASP.NET Core 6.0+
  • Blazor Server and WebAssembly
  • MAUI applications

Get a Free API Key

AI agents can sign up with a verified email in two steps — no dashboard, no human required.

Step 1: Request a verification code

curl -X POST https://oddsockets.com/api/agent-signup \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "agentName": "my-agent", "platform": "csharp"}'

Step 2: Verify the 6-digit code from your email and get your API key

curl -X POST https://oddsockets.com/api/agent-signup/verify \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "code": "123456", "agentName": "my-agent"}'

Plans

Free Starter Pro
Price $0/mo $49.99/mo $299/mo
MAU 100 1,000 50,000
Concurrent connections 50 1,000 Unlimited
Messages/day 10,000 4,320,000 Unlimited
Channels 10 Unlimited Unlimited
Storage 100MB (24h) 50GB (6 months) Unlimited

All limits are enforced in real time.

Support

License

MIT License - Copyright (c) 2026 Joe Wee, Tyga.Cloud Ltd. See LICENSE for details.

About

C#/.NET SDK for OddSockets — real-time WebSocket channels, pub/sub, presence.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages