### Run Console Example with dotnet CLI
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/examples/README.md
Executes the .NET Console Example application using the dotnet CLI. This can be run from the repository root or the example's directory.
```bash
dotnet run --project examples/Centrifugal.Centrifuge.ConsoleExample/Centrifugal.Centrifuge.ConsoleExample.csproj
```
```bash
cd examples/Centrifugal.Centrifuge.ConsoleExample
dotnet run
```
--------------------------------
### InitializeBrowserInterop Example
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Example demonstrating how to initialize browser interop in Program.cs for Blazor applications.
```csharp
builder.Services.AddCentrifugeClient();
// or
var jsRuntime = /* ... */;
CentrifugeClient.InitializeBrowserInterop(jsRuntime);
```
--------------------------------
### Run Blazor Example (Bash)
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/examples/Centrifugal.Centrifuge.BlazorExample/README.md
Execute this command from the repository root to build and run the Blazor WebAssembly example.
```bash
make run-blazor-example
```
--------------------------------
### Run Blazor Example Manually (Bash)
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/examples/Centrifugal.Centrifuge.BlazorExample/README.md
Navigate to the example directory and run the Blazor application manually, specifying the URLs.
```bash
cd examples/Centrifugal.Centrifuge.BlazorExample
dotnet run --urls "http://localhost:5050" --launch-profile "http"
```
--------------------------------
### Run Console Example with Make
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/examples/README.md
Executes the .NET Console Example application using the provided Make command from the repository root.
```bash
make run-example
```
--------------------------------
### PublishAsync Example
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Example demonstrating how to publish a UTF-8 encoded message to the 'announcements' channel.
```csharp
var message = System.Text.Encoding.UTF8.GetBytes("Hello, world!");
await client.PublishAsync("announcements", message);
```
--------------------------------
### PresenceAsync Example
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Example demonstrating how to retrieve presence information for the 'chat' channel and display client details.
```csharp
var presence = await client.PresenceAsync("chat");
foreach (var kvp in presence.Clients)
{
Console.WriteLine($"Client {kvp.Key}: User {kvp.Value.User}");
}
```
--------------------------------
### HistoryAsync Example
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Example showing how to fetch the last 20 publications from the 'chat' channel and print their data.
```csharp
var history = await client.HistoryAsync("chat", new CentrifugeHistoryOptions { Limit = 20 });
foreach (var pub in history.Publications)
{
Console.WriteLine(System.Text.Encoding.UTF8.GetString(pub.Data.Span));
}
```
--------------------------------
### PresenceStatsAsync Example
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Example showing how to fetch and display presence statistics for the 'chat' channel.
```csharp
var stats = await client.PresenceStatsAsync("chat");
Console.WriteLine($"Clients: {stats.NumClients}, Users: {stats.NumUsers}");
```
--------------------------------
### xUnit Test Example
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/CONTRIBUTING.md
An example of a unit test written using the xUnit framework, following the Arrange, Act, Assert pattern.
```csharp
[Fact]
public async Task Connect_WithValidEndpoint_ChangesStateToConnecting()
{
// Arrange
var client = new CentrifugeClient("ws://localhost:8000/connection/websocket");
var stateChanged = false;
client.StateChanged += (sender, args) =>
{
if (args.NewState == ClientState.Connecting)
{
stateChanged = true;
}
};
// Act
_ = client.ConnectAsync();
await Task.Delay(100);
// Assert
Assert.True(stateChanged);
}
```
--------------------------------
### Waiting for Connection and Subscription Readiness in C#
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Provides examples of how to asynchronously wait for the client to be connected using `ReadyAsync()` after calling `Connect()`, and for a subscription to be ready after calling `Subscribe()`.
```csharp
client.Connect();
await client.ReadyAsync(); // Wait until connected
subscription.Subscribe();
await subscription.ReadyAsync(); // Wait until subscribed
```
--------------------------------
### SetTagsFilter Examples
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-subscription.md
Demonstrates how to use SetTagsFilter with a simple equality check and a complex filter involving logical AND and greater-than operators.
```csharp
// Only receive publications where ticker="BTC"
sub.SetTagsFilter(CentrifugeFilterNodeBuilder.Eq("ticker", "BTC"));
```
```csharp
// Complex filter with logical operators
sub.SetTagsFilter(
CentrifugeFilterNodeBuilder.And(
CentrifugeFilterNodeBuilder.Eq("ticker", "BTC"),
CentrifugeFilterNodeBuilder.Gt("price", "50000")
)
);
```
--------------------------------
### Example Async Method with Exception Handling
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/CONTRIBUTING.md
Illustrates an asynchronous method with state locking and exception handling, including XML documentation comments for public APIs.
```csharp
///
/// Connects to the Centrifugo server asynchronously.
///
/// Cancellation token.
/// A task representing the asynchronous operation.
/// Thrown when connection fails.
public async Task ConnectAsync(CancellationToken cancellationToken = default)
{
await _stateLock.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
// Implementation
}
finally
{
_stateLock.Release();
}
}
```
--------------------------------
### Build Centrifuge-CSharp Project
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Clone the repository, navigate to the project directory, and use dotnet CLI commands to build, test, and pack the NuGet package. Ensure you have the .NET SDK installed.
```bash
# Clone the repository
git clone https://github.com/centrifugal/centrifuge-csharp.git
cd centrifuge-csharp
# Build the project
dotnet build
# Run tests
dotnet test
# Pack NuGet package
dotnet pack -c Release
```
--------------------------------
### Install Centrifuge C# SDK via .NET CLI
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Use this command to add the Centrifuge C# SDK package to your project using the .NET CLI.
```bash
dotnet add package Centrifugal.Centrifuge
```
--------------------------------
### Example Usage of CentrifugeRpcResult
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/types.md
Demonstrates how to call an RPC method and deserialize the response data from CentrifugeRpcResult.
```csharp
var result = await client.RpcAsync("method", data);
var response = System.Text.Json.JsonSerializer.Deserialize(result.Data.Span);
```
--------------------------------
### Create Subscription with Tags Filter
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Configure server-side filtering for publications based on tags. This example filters for publications with ticker 'BTC' and price greater than '50000'.
```csharp
var options = new CentrifugeSubscriptionOptions
{
TagsFilter = CentrifugeFilterNodeBuilder.And(
CentrifugeFilterNodeBuilder.Eq("ticker", "BTC"),
CentrifugeFilterNodeBuilder.Gt("price", "50000")
)
};
var sub = client.NewSubscription("prices", options);
sub.Subscribe();
```
--------------------------------
### Add Pre-release Package Version
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/PUBLISHING.md
Installs a specific pre-release version of the Centrifuge.Client NuGet package using the .NET CLI.
```bash
dotnet add package Centrifuge.Client --version 1.1.0-beta.1
```
--------------------------------
### Configure Subscription Recovery and Positioning
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Set up subscription options to enable recovery and positioning. This allows the client to resume subscriptions from a specific point after a disconnection, provided the server supports it. Use 'Since' to specify the starting position.
```csharp
var options = new CentrifugeSubscriptionOptions
{
// Enable recovery (if supported by server)
Recoverable = true,
// Enable positioning
Positioned = true,
// Start from known position
Since = new CentrifugeStreamPosition(offset: 100, epoch: "epoch-id")
};
var subscription = client.NewSubscription("chat", options);
subscription.Subscribed += (sender, e) =>
{
if (e.WasRecovering)
{
Console.WriteLine($"Recovery attempted, recovered: {e.Recovered}");
}
};
subscription.Subscribe();
```
--------------------------------
### Get Channel Presence Statistics
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-subscription.md
Gets presence statistics for the channel, such as the number of connected clients and unique users. This method automatically waits for the subscription to be ready.
```csharp
public async Task PresenceStatsAsync(
CancellationToken cancellationToken = default)
```
```csharp
var stats = await subscription.PresenceStatsAsync();
Console.WriteLine($"Clients: {stats.NumClients}, Users: {stats.NumUsers}");
```
--------------------------------
### Centrifuge C# SDK Initialization in Unity
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Example of initializing and connecting the Centrifuge C# SDK within a Unity MonoBehaviour. Ensure your Unity version supports .NET Standard 2.1. For WebGL builds, a compatible WebSocket plugin is required.
```csharp
using UnityEngine;
using Centrifugal.Centrifuge;
using System.Threading.Tasks;
public class CentrifugeManager : MonoBehaviour
{
private CentrifugeClient client;
async void Start()
{
client = new CentrifugeClient("ws://localhost:8000/connection/websocket");
client.Connected += (sender, e) =>
{
Debug.Log($
```
```csharp
client.Connect();
}
void OnDestroy()
{
if (client != null)
{
// Dispose() blocks until disconnect completes
client.Dispose();
}
}
}
```
--------------------------------
### Run Centrifugo Server with Docker
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/examples/README.md
Launches a Centrifugo server instance using Docker with specific configurations for example purposes. Note the insecure client mode and wildcard allowed origins, which should be avoided in production.
```bash
docker pull centrifugo/centrifugo:v6
docker run -p 8000:8000 \
-e CENTRIFUGO_ADMIN_ENABLED="true" \
-e CENTRIFUGO_ADMIN_PASSWORD="change-me-to-secure-password" \
-e CENTRIFUGO_ADMIN_SECRET="change-me-to-secure-secret" \
-e CENTRIFUGO_HTTP_STREAM_ENABLED="true" \
-e CENTRIFUGO_CLIENT_INSECURE="true" \
-e CENTRIFUGO_CLIENT_ALLOWED_ORIGINS="*" \
-e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_DELTA_PUBLISH="true" \
-e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_PRESENCE="true" \
-e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_JOIN_LEAVE="true" \
-e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_FORCE_PUSH_JOIN_LEAVE="true" \
-e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_HISTORY_SIZE="100" \
-e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_HISTORY_TTL="300s" \
-e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_FORCE_RECOVERY="true" \
-e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_ALLOW_PUBLISH_FOR_SUBSCRIBER="true" \
-e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_ALLOW_PRESENCE_FOR_SUBSCRIBER="true" \
-e CENTRIFUGO_CHANNEL_WITHOUT_NAMESPACE_ALLOW_HISTORY_FOR_SUBSCRIBER="true" \
-e CENTRIFUGO_CLIENT_SUBSCRIBE_TO_USER_PERSONAL_CHANNEL_ENABLED="true" \
-e CENTRIFUGO_LOG_LEVEL="trace" \
centrifugo/centrifugo:v6 centrifugo
```
--------------------------------
### Configure Centrifuge Client in Blazor WebAssembly
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Register Centrifuge client services in Program.cs for automatic initialization of browser interop. This setup is for Blazor WebAssembly applications.
```csharp
using Centrifugal.Centrifuge;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
// Add Centrifuge client services - automatically initializes browser interop
builder.Services.AddCentrifugeClient();
await builder.Build().RunAsync();
```
--------------------------------
### Install Centrifuge C# SDK via Package Manager Console
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Use this command to add the Centrifuge C# SDK package to your project using the Package Manager Console in Visual Studio.
```powershell
Install-Package Centrifugal.Centrifuge
```
--------------------------------
### Get Channel Presence Information
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Shows how to use the PresenceAsync and PresenceStatsAsync methods to retrieve information about connected clients and users in a channel. It iterates through clients to display their IDs and user information.
```csharp
// Get all clients in channel
var presence = await subscription.PresenceAsync();
foreach (var client in presence.Clients.Values)
{
Console.WriteLine($"Client: {client.Client}, User: {client.User}");
}
// Get presence stats (counts only)
var stats = await subscription.PresenceStatsAsync();
Console.WriteLine($"Clients: {stats.NumClients}, Users: {stats.NumUsers}");
```
--------------------------------
### Check if String Starts With Prefix
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/filters.md
Use the 'StartsWith' operator to filter based on whether a tag's string value begins with a specific prefix. This is useful for pattern matching at the beginning of a string.
```csharp
public static CentrifugeFilterNode StartsWith(string key, string prefix)
```
```csharp
CentrifugeFilterNodeBuilder.StartsWith("ticker", "BTC")
// Matches: {"ticker": "BTCUSD"}, {"ticker": "BTCEUR"}
// Doesn't match: {"ticker": "ETHBTC"}
```
--------------------------------
### Create and Manage Subscriptions
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Demonstrates creating a new subscription, setting up event handlers for various subscription states (publication, subscribing, subscribed, unsubscribed), subscribing to a channel, publishing messages, and unsubscribing.
```csharp
// Create subscription, may throw CentrifugeDuplicateSubscriptionException
// if subscription to the channel already exists in Client's registry.
var subscription = client.NewSubscription("chat");
// Setup subscription event handlers
subscription.Publication += (sender, e) =>
{
var data = Encoding.UTF8.GetString(e.Data.Span);
Console.WriteLine($"Message from {e.Channel}: {data}");
};
subscription.Subscribing += (sender, e) =>
{
Console.WriteLine("Subscribing to channel");
};
subscription.Subscribed += (sender, e) =>
{
Console.WriteLine($"Subscribed to channel, recovered: {e.Recovered}");
};
subscription.Unsubscribed += (sender, e) =>
{
Console.WriteLine($"Unsubscribed: {e.Code} - {e.Reason}");
};
// Subscribe to channel (non-blocking)
subscription.Subscribe();
// Publish to channel - automatically waits for subscription to be ready
var message = Encoding.UTF8.GetBytes("Hello, world!");
await subscription.PublishAsync(message);
// Unsubscribe when done
subscription.Unsubscribe();
```
--------------------------------
### Build and Test Project
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/CONTRIBUTING.md
Commands to restore dependencies, build the project, and run tests.
```bash
# Restore dependencies
dotnet restore
# Build the project
dotnet build
# Run tests
dotnet test
# Run a specific test
dotnet test --filter "FullyQualifiedName~ClientTests"
```
--------------------------------
### Get Channel Presence Information
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-subscription.md
Gets presence information for the channel, including connected clients and their associated user IDs. This method automatically waits for the subscription to be ready.
```csharp
public async Task PresenceAsync(
CancellationToken cancellationToken = default)
```
```csharp
var presence = await subscription.PresenceAsync();
foreach (var kvp in presence.Clients)
{
Console.WriteLine($"Client {kvp.Key}: User {kvp.Value.User}");
}
```
--------------------------------
### Clone and Navigate Repository
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/CONTRIBUTING.md
Clone your forked repository and navigate into the project directory.
```bash
git clone https://github.com/YOUR_USERNAME/centrifuge-csharp.git
cd centrifuge-csharp
```
--------------------------------
### Get History
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/README.md
Retrieves the publication history for a subscription, with an option to limit the number of results.
```APIDOC
## Get History
### Description
Retrieves the publication history for a subscription, with an option to limit the number of results.
### Method
```csharp
var history = await sub.HistoryAsync(new CentrifugeHistoryOptions { Limit = 20 });
foreach (var pub in history.Publications) { /* ... */ }
```
```
--------------------------------
### Initialize Git Repository and Push
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/PUBLISHING.md
Initializes a Git repository, adds files, commits them, sets the remote origin, and pushes the main branch to GitHub.
```bash
cd centrifuge-csharp
# Initialize git
git init
# Add files
git add .
# Commit
git commit -m "Initial commit: Centrifuge C# SDK v1.0.0"
# Add remote (replace with your repository URL)
git remote add origin https://github.com/centrifugal/centrifuge-csharp.git
# Push to GitHub
git branch -M main
git push -u origin main
```
--------------------------------
### Create Subscription with Token and Join/Leave Events
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Configure a subscription with an initial JWT token for authentication and enable receiving join/leave notifications.
```csharp
var options = new CentrifugeSubscriptionOptions
{
Token = "channel-token-123",
JoinLeave = true
};
var sub = client.NewSubscription("private-channel", options);
sub.Subscribe();
```
--------------------------------
### PresenceAsync Method Signature
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Signature for getting presence information for a channel, listing all connected clients.
```csharp
public async Task PresenceAsync(string channel, CancellationToken cancellationToken = default)
```
--------------------------------
### PresenceAsync
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-subscription.md
Gets presence information for the channel, including connected clients. This method automatically waits for the subscription to be ready.
```APIDOC
## PresenceAsync
### Description
Gets presence information for the channel. Automatically waits for subscription to be ready.
### Method Signature
```csharp
public async Task PresenceAsync(CancellationToken cancellationToken = default)
```
### Parameters
#### Query Parameters
- **cancellationToken** (CancellationToken) - Optional - Cancellation token to abort the operation.
### Returns
`CentrifugePresenceResult` with client information.
### Example
```csharp
var presence = await subscription.PresenceAsync();
foreach (var kvp in presence.Clients)
{
Console.WriteLine($"Client {kvp.Key}: User {kvp.Value.User}");
}
```
```
--------------------------------
### Manage Subscription Filters
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/filters.md
Demonstrates how to set an initial filter before subscribing, change the filter dynamically during an active subscription, and remove filters.
```csharp
var sub = client.NewSubscription("chat");
// Set initial filter before subscribing
sub.SetTagsFilter(CentrifugeFilterNodeBuilder.Eq("channel", "general"));
sub.Subscribe();
// Change filter during subscription (takes effect on next message batch)
sub.SetTagsFilter(CentrifugeFilterNodeBuilder.Eq("channel", "announcements"));
// Remove filter
sub.SetTagsFilter(null);
```
--------------------------------
### Create Subscription with GetState Callback
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Implement a callback to fetch the application's current state and stream position. Ensure the position is read before the data to maintain consistency for recovery.
```csharp
var options = new CentrifugeSubscriptionOptions
{
GetState = async (channel) =>
{
// IMPORTANT: Read position FIRST, then data
var positionResponse = await database.GetStreamPositionAsync(channel);
var dataResponse = await database.GetDataAsync(channel);
// Render data to UI...
UI.Render(dataResponse);
// Return position for recovery
return new CentrifugeStreamPosition(
offset: positionResponse.Offset,
epoch: positionResponse.Epoch
);
}
};
var sub = client.NewSubscription("stream", options);
sub.Subscribe();
```
--------------------------------
### CentrifugeHistoryOptions
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Options for history requests. Allows configuration of the number of publications, the starting point for retrieval, and the order of results.
```APIDOC
## Class CentrifugeHistoryOptions
### Description
Options for history requests. Allows configuration of the number of publications, the starting point for retrieval, and the order of results.
### Namespace
Centrifugal.Centrifuge
### Location
src/Centrifugal.Centrifuge/HistoryOptions.cs
### Properties
- **Limit** (int?) - Optional - Maximum number of publications to return. If null or not set, only stream position is returned (no publications).
- **Since** (CentrifugeStreamPosition?) - Optional - Stream position to get publications since. If set, returns publications after this position.
- **Reverse** (bool) - Optional - Default: false - Return publications in reverse order (newest first).
### Example: Get Last 20 Messages
```csharp
var history = await subscription.HistoryAsync(new CentrifugeHistoryOptions
{
Limit = 20
});
foreach (var pub in history.Publications)
{
var message = System.Text.Encoding.UTF8.GetString(pub.Data.Span);
Console.WriteLine(message);
}
```
### Example: Get Messages Since Position
```csharp
var lastPosition = new CentrifugeStreamPosition(offset: 100, epoch: "epoch-1");
var history = await subscription.HistoryAsync(new CentrifugeHistoryOptions
{
Limit = 50,
Since = lastPosition
});
Console.WriteLine($"Recovered {history.Publications.Length} publications");
Console.WriteLine($"New position: {history.Offset} (epoch: {history.Epoch})");
```
### Example: Get Newest Messages First
```csharp
var history = await subscription.HistoryAsync(new CentrifugeHistoryOptions
{
Limit = 10,
Reverse = true // Newest first
});
```
```
--------------------------------
### Manual NuGet Package Publishing Workflow
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/PUBLISHING.md
A sequence of .NET CLI commands to clean, restore, build, test, pack, and manually push a NuGet package to a specified source. Ensure to replace YOUR_API_KEY with your actual NuGet API key.
```bash
# 1. Clean and restore
dotnet clean
dotnet restore
# 2. Build in Release mode
dotnet build --configuration Release
# 3. Run tests
dotnet test --configuration Release
# 4. Pack the NuGet package
dotnet pack src/Centrifuge/Centrifuge.csproj --configuration Release --output ./artifacts
# 5. Publish to NuGet.org
dotnet nuget push ./artifacts/Centrifuge.Client.*.nupkg \
--api-key YOUR_API_KEY \
--source https://api.nuget.org/v3/index.json
```
--------------------------------
### Handle OperationCanceledException
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/exceptions.md
Example of catching OperationCanceledException for cancelled or timed-out operations. This typically indicates user cancellation or a timeout event.
```csharp
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
try
{
await client.ReadyAsync(cancellationToken: cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Cancelled or timed out");
}
```
--------------------------------
### Handle CentrifugeDuplicateSubscriptionException
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/exceptions.md
Example of catching CentrifugeDuplicateSubscriptionException to reuse an existing subscription. Ensure to check for the subscription's existence before attempting to reuse it.
```csharp
try
{
var sub = client.NewSubscription("chat");
}
catch (CentrifugeDuplicateSubscriptionException ex)
{
Console.WriteLine($"Subscription to {ex.Channel} already exists");
var existing = client.GetSubscription(ex.Channel);
if (existing != null)
{
existing.Subscribe(); // Reuse existing
}
}
```
--------------------------------
### Handling CentrifugeUnauthorizedException
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/exceptions.md
Example of configuring a token retrieval mechanism that throws `CentrifugeUnauthorizedException` on failure, and handling this specific exception during client connection.
```csharp
var options = new CentrifugeClientOptions
{
GetToken = async () =>
{
try
{
return await FetchNewTokenAsync();
}
catch
{
throw new CentrifugeUnauthorizedException("Failed to obtain token");
}
}
};
try
{
await client.ReadyAsync();
}
catch (CentrifugeUnauthorizedException)
{
Console.WriteLine("Authentication failed, user must log in");
}
```
--------------------------------
### Async Disposal with await using
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Recommended pattern for proper asynchronous resource management and connection closure using 'await using'.
```csharp
await using var client = new CentrifugeClient("ws://localhost:8000/connection/websocket");
client.Connect();
// ...
// DisposeAsync called automatically
```
--------------------------------
### Batching Subscriptions in C#
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Demonstrates how to leverage the non-async `Subscribe()` method to batch multiple subscription requests into a single protocol message when `Connect()` is called.
```csharp
var sub1 = client.NewSubscription("channel1");
var sub2 = client.NewSubscription("channel2");
var sub3 = client.NewSubscription("channel3");
sub1.Subscribe();
sub2.Subscribe();
sub3.Subscribe();
client.Connect();
// All 3 subscriptions are batched together in one request!
```
--------------------------------
### Get Last 20 Messages
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Use CentrifugeHistoryOptions to specify the maximum number of publications to retrieve. The publications are iterated and decoded from UTF-8.
```csharp
var history = await subscription.HistoryAsync(new CentrifugeHistoryOptions
{
Limit = 20
});
foreach (var pub in history.Publications)
{
var message = System.Text.Encoding.UTF8.GetString(pub.Data.Span);
Console.WriteLine(message);
}
```
--------------------------------
### Get Newest Messages First
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Set 'Reverse' to true in CentrifugeHistoryOptions to retrieve publications in descending order, with the newest messages appearing first.
```csharp
var history = await subscription.HistoryAsync(new CentrifugeHistoryOptions
{
Limit = 10,
Reverse = true // Newest first
});
```
--------------------------------
### Create and Subscribe to a Channel
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Creates a new subscription to a channel. The subscription is not automatically subscribed. Call Subscribe() on the returned instance to initiate subscription.
```csharp
var sub = client.NewSubscription("chat");
sub.Subscribe();
```
--------------------------------
### Create Subscription with Recovery Options
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Configure a subscription for message recovery by enabling 'Recoverable' and 'Positioned' modes. Adjust resubscribe delays for optimal backoff strategy.
```csharp
var options = new CentrifugeSubscriptionOptions
{
Recoverable = true,
Positioned = true,
MinResubscribeDelay = TimeSpan.FromMilliseconds(100),
MaxResubscribeDelay = TimeSpan.FromSeconds(30)
};
var sub = client.NewSubscription("stream", options);
sub.Subscribe();
```
--------------------------------
### Subscribe to a Channel
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-subscription.md
Initiates a subscription to a channel. This method is non-blocking and the subscription process occurs in the background. Use `ReadyAsync` to wait for the subscription to be established.
```csharp
public void Subscribe()
```
```csharp
subscription.Subscribe();
await subscription.ReadyAsync(); // Wait for subscription
```
--------------------------------
### ReadyAsync
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-subscription.md
Waits for the subscription to be established. If the subscription is already active, the task completes immediately. Supports optional timeouts and cancellation tokens.
```APIDOC
## ReadyAsync
### Description
Returns a task that completes when subscription is established. If already subscribed, completes immediately.
### Method Signature
```csharp
public Task ReadyAsync(TimeSpan? timeout = null, CancellationToken cancellationToken = default)
```
### Parameters
#### Query Parameters
- **timeout** (TimeSpan?) - Optional - Optional timeout duration for establishing the subscription.
- **cancellationToken** (CancellationToken) - Optional - Cancellation token to abort the operation.
### Returns
Task that completes when subscribed.
### Throws
- `CentrifugeException` - if subscription becomes unsubscribed
- `OperationCanceledException` - if timeout or cancellation occurs
### Example
```csharp
try
{
await subscription.ReadyAsync(timeout: TimeSpan.FromSeconds(10));
Console.WriteLine("Subscribed!");
}
catch (OperationCanceledException)
{
Console.WriteLine("Subscription timeout");
}
```
```
--------------------------------
### Wait for Subscription Readiness
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-subscription.md
Returns a task that completes when the subscription is established. If already subscribed, it completes immediately. Handles optional timeouts and cancellation tokens.
```csharp
public Task ReadyAsync(TimeSpan? timeout = null, CancellationToken cancellationToken = default)
```
```csharp
try
{
await subscription.ReadyAsync(timeout: TimeSpan.FromSeconds(10));
Console.WriteLine("Subscribed!");
}
catch (OperationCanceledException)
{
Console.WriteLine("Subscription timeout");
}
```
--------------------------------
### Change Centrifuge Client Server URL
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/examples/README.md
Demonstrates how to configure the Centrifuge client to connect to a different Centrifugo server URL. Ensure the provided URL is correct for your setup.
```csharp
var client = new CentrifugeClient("ws://your-server:8000/connection/websocket", options);
```
--------------------------------
### Example of Unhandled Exception in Event Handler
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
This code demonstrates an unhandled exception within an event handler. The SDK does not guarantee behavior for unhandled exceptions, which can lead to unpredictable results.
```csharp
// ❌ BAD: Unhandled exceptions - behavior is undefined
subscription.Publication += async (sender, e) =>
{
await riskyOperation(); // If this throws - undefined behavior!
};
```
--------------------------------
### Dynamic Subscription Creation and Management
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/advanced-patterns.md
Dynamically create subscriptions as needed and manage them using `NewSubscription`, `GetSubscription`, and `RemoveSubscription`.
```csharp
public class ChatManager
{
private readonly CentrifugeClient _client;
public async Task JoinChannelAsync(string channel)
{
if (_client.GetSubscription(channel) != null)
{
return; // Already subscribed
}
var sub = _client.NewSubscription(channel);
sub.Publication += (sender, e) =>
{
OnMessageReceived(channel, e);
};
sub.Subscribe();
await sub.ReadyAsync();
}
public void LeaveChannel(string channel)
{
var sub = _client.GetSubscription(channel);
if (sub != null)
{
_client.RemoveSubscription(sub); // Also calls Unsubscribe
}
}
}
```
--------------------------------
### Get Messages Since Position
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Configure history requests to fetch publications after a specific stream position using the 'Since' property. The offset and epoch of the new position are then logged.
```csharp
var lastPosition = new CentrifugeStreamPosition(offset: 100, epoch: "epoch-1");
var history = await subscription.HistoryAsync(new CentrifugeHistoryOptions
{
Limit = 50,
Since = lastPosition
});
Console.WriteLine($"Recovered {history.Publications.Length} publications");
Console.WriteLine($"New position: {history.Offset} (epoch: {history.Epoch})");
```
--------------------------------
### Create Subscription with Delta Compression
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Enable delta compression using the 'fossil' format for bandwidth optimization. This cannot be used with tags filtering.
```csharp
var options = new CentrifugeSubscriptionOptions
{
Delta = "fossil"
};
var sub = client.NewSubscription("large-state", options);
sub.Subscribe();
```
--------------------------------
### Subscribe to a Different Channel
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/examples/README.md
Illustrates how to subscribe to a different channel by providing the channel name when creating a new subscription. Replace 'your-channel-name' with the desired channel.
```csharp
var subscription = client.NewSubscription("your-channel-name");
```
--------------------------------
### Custom Centrifuge Client Options with IJSRuntime
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Configure Centrifuge client options by explicitly passing an IJSRuntime instance. This is useful when you need to manage the IJSRuntime manually, for example, within a Blazor component.
```csharp
var options = new CentrifugeClientOptions
{
JSRuntime = jsRuntime // From @inject IJSRuntime in component
};
var client = new CentrifugeClient("ws://localhost:8000/connection/websocket", options);
```
--------------------------------
### Fast Local Operation in C# Event Handler
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/advanced-patterns.md
Keep event handlers quick by performing only local operations to avoid blocking the receive thread. This example updates local state variables.
```csharp
// ✅ GOOD: Quick local operation
subscription.Publication += (sender, e) =>
{
_lastMessage = e.Data;
_messageCount++;
};
```
--------------------------------
### Subscription Creation
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-subscription.md
Demonstrates how to create a new subscription to a channel using the CentrifugeClient.
```APIDOC
## Subscription Creation
Subscriptions are created via `CentrifugeClient.NewSubscription()`:
```csharp
var subscription = client.NewSubscription("chat", options);
```
```
--------------------------------
### Connect to Centrifuge Server
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Initiates the connection process. The connection happens asynchronously in the background. Use ReadyAsync to wait for the connection to be established.
```csharp
client.Connect();
await client.ReadyAsync(); // Wait for connection
```
--------------------------------
### Subscribe to a Channel and Receive Publications
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/README.md
Creates a subscription to a specified channel, listens for incoming publications, and allows publishing messages. Ensure the client is connected and ready before subscribing.
```csharp
var sub = client.NewSubscription("chat");
sub.Publication += (sender, e) =>
{
var message = System.Text.Encoding.UTF8.GetString(e.Data.Span);
Console.WriteLine($"Message: {message}");
};
sub.Subscribe();
await sub.ReadyAsync();
// Publish
await sub.PublishAsync(System.Text.Encoding.UTF8.GetBytes("Hello!"));
```
--------------------------------
### Blazor Component Centrifuge Client Usage
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Example of a Blazor component that creates and uses a Centrifuge client to connect, subscribe to a channel, and display incoming messages. Ensure the JavaScript interop modules are included in index.html.
```csharp
@page "/"
@inject IJSRuntime JS
@inject ILoggerFactory LoggerFactory
@implements IAsyncDisposable
@using System.Text
Messages
@foreach (var msg in messages)
{
- @msg
}
@code {
private CentrifugeClient? _client;
private List messages = new();
protected override async Task OnInitializedAsync()
{
// Create client directly - no need to pass IJSRuntime
_client = new CentrifugeClient(
"ws://localhost:8000/connection/websocket",
options: new CentrifugeClientOptions
{
Logger = LoggerFactory.CreateLogger()
}
);
_client.Connected += (sender, e) =>
{
messages.Add($"Connected: {e.ClientId}");
InvokeAsync(StateHasChanged);
};
var subscription = _client.NewSubscription("chat");
subscription.Publication += (sender, e) =>
{
var data = Encoding.UTF8.GetString(e.Data.Span);
messages.Add($"Received: {data}");
InvokeAsync(StateHasChanged);
};
_client.Connect();
subscription.Subscribe();
}
public async ValueTask DisposeAsync()
{
if (_client != null)
{
await _client.DisposeAsync();
}
}
}
```
--------------------------------
### Create and Push Version Tag for Automatic Publishing
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/PUBLISHING.md
Creates a Git tag for a specific version and pushes it to the remote repository to trigger the automatic GitHub Actions workflow for building, testing, packing, and publishing the NuGet package.
```bash
# 2. Create and push a version tag
git tag v1.0.0
git push origin v1.0.0
```
--------------------------------
### Run Tests with Coverage and Filters
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/CONTRIBUTING.md
Commands to execute all tests, run tests with code coverage, and filter tests by category.
```bash
# Run all tests
dotnet test
# Run with coverage
dotnet test --collect:"XPlat Code Coverage"
# Run integration tests (requires Centrifugo server)
dotnet test --filter "Category=Integration"
```
--------------------------------
### Basic Centrifuge Client Connection in C#
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Establishes a basic WebSocket connection to a Centrifuge server and sets up event handlers for connection status. Recommended to use 'await using' for proper async disposal.
```csharp
using Centrifugal.Centrifuge;
// Recommended: Use 'await using' for proper async disposal
await using var client = new CentrifugeClient("ws://localhost:8000/connection/websocket");
// Setup event handlers
client.Connecting += (sender, e) =>
{
Console.WriteLine($"[Client] Connecting: {e.Code} - {e.Reason}");
};
client.Connected += (sender, e) =>
{
Console.WriteLine($"Connected with client ID: {e.ClientId}");
};
client.Disconnected += (sender, e) =>
{
Console.WriteLine($"Disconnected: {e.Code} - {e.Reason}");
};
client.Error += (sender, e) =>
{
Console.WriteLine($"Error: {e.Message}");
};
// Connect to server (non-blocking)
client.Connect();
// Use client methods - they automatically wait for connection
var result = await client.RpcAsync("method", data);
// DisposeAsync is called automatically at the end of the 'await using' block
// It waits for disconnect to complete before releasing resources
```
--------------------------------
### Basic Connection to Centrifuge
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/README.md
Establishes a WebSocket connection to the Centrifuge server. Use `ReadyAsync()` to ensure the client is connected before proceeding.
```csharp
using Centrifugal.Centrifuge;
var client = new CentrifugeClient("ws://localhost:8000/connection/websocket");
client.Connected += (sender, e) =>
{
Console.WriteLine($"Connected: {e.ClientId}");
};
client.Connect();
await client.ReadyAsync();
// Use client...
```
--------------------------------
### Benchmark Connection Lifecycle Timing
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/advanced-patterns.md
Measure the time taken for a client to establish a connection and become ready. Ensure the client is initialized before use.
```csharp
var sw = System.Diagnostics.Stopwatch.StartNew();
client.Connect();
await client.ReadyAsync();
sw.Stop();
Console.WriteLine($"Connection took {sw.ElapsedMilliseconds}ms");
```
--------------------------------
### InitializeBrowserInterop Method Signature
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Signature for initializing browser interop, required for Blazor WebAssembly support. Call this once at application startup.
```csharp
public static void InitializeBrowserInterop(Microsoft.JSInterop.IJSRuntime jsRuntime)
```
--------------------------------
### Create a New Subscription
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-subscription.md
Use this method to create a new subscription to a specified channel. Options can be provided to configure the subscription.
```csharp
var subscription = client.NewSubscription("chat", options);
```
--------------------------------
### Tag and Push Pre-release Version
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/PUBLISHING.md
Creates and pushes a Git tag for a pre-release version to the remote repository.
```bash
git tag v1.1.0-beta.1
git push origin v1.1.0-beta.1
```
--------------------------------
### Publish Data to a Channel
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/README.md
Creates a new subscription to a channel, subscribes to it, and publishes data. Ensure the channel name is valid and the client is connected.
```csharp
var sub = client.NewSubscription("channel");
sub.Subscribe();
await sub.PublishAsync(data);
```
--------------------------------
### Handle CentrifugeConfigurationException
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/exceptions.md
Demonstrates how to catch and handle CentrifugeConfigurationException when creating a Centrifuge client with invalid options. Fix the configuration before retrying.
```csharp
try
{
var options = new CentrifugeClientOptions
{
Timeout = TimeSpan.FromSeconds(-1) // INVALID!
};
var client = new CentrifugeClient("ws://localhost:8000", options);
}
catch (CentrifugeConfigurationException ex)
{
Console.WriteLine($"Invalid config: {ex.Message}");
// Fix: use positive timeout
}
```
--------------------------------
### Non-Async Connect and Subscribe in C#
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Illustrates the non-asynchronous nature of `Connect()` and `Subscribe()` methods, which are designed for internal lifecycle management and automatic batching.
```csharp
client.Connect(); // Returns void, not Task
subscription.Subscribe(); // Returns void, not Task
```
--------------------------------
### StartsWith
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/filters.md
Checks if a tag value begins with a specified prefix string. Useful for filtering based on partial string matches at the beginning of a tag value.
```APIDOC
## StartsWith
### Description
Checks if a tag value starts with the specified prefix.
### Method Signature
```csharp
public static CentrifugeFilterNode StartsWith(string key, string prefix)
```
### Parameters
- **key** (string) - Required - Tag name
- **prefix** (string) - Required - Prefix to match
### Example
```csharp
CentrifugeFilterNodeBuilder.StartsWith("ticker", "BTC")
// Matches: {"ticker": "BTCUSD"}, {"ticker": "BTCEUR"}
// Doesn't match: {"ticker": "ETHBTC"}
```
```
--------------------------------
### Create Subscription with Token Refresh Callback
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/configuration.md
Configure a subscription to dynamically fetch or refresh its JWT token using a provided asynchronous callback. This is useful for time-limited tokens.
```csharp
var options = new CentrifugeSubscriptionOptions
{
GetToken = async (channel) =>
{
var response = await httpClient.PostAsJsonAsync("https://myapp.com/centrifugo/sub_token",
new { channel });
var body = await response.Content.ReadAsAsync();
return body.Token;
}
};
var sub = client.NewSubscription("chat", options);
sub.Subscribe();
```
--------------------------------
### Configure Centrifuge Client with Logging
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/advanced-patterns.md
Set up a Centrifuge client with custom logger options. Debug logs provide insights into connection lifecycle and transport operations.
```csharp
var loggerFactory = new ConsoleLoggerFactory();
var options = new CentrifugeClientOptions
{
Logger = loggerFactory.CreateLogger(),
Name = "my-app",
Version = "1.0.0"
};
var client = new CentrifugeClient("ws://localhost:8000/connection/websocket", options);
// Debug logs will show connection lifecycle, transport operations, etc.
```
--------------------------------
### InitializeBrowserInterop
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/api-client.md
Initializes browser interop functionality, specifically for Blazor WebAssembly applications. This should be called once during application startup.
```APIDOC
## InitializeBrowserInterop
### Description
Initializes browser interop for Blazor WebAssembly support. Call once at application startup.
### Method Signature
```csharp
public static void InitializeBrowserInterop(Microsoft.JSInterop.IJSRuntime jsRuntime)
```
### Parameters
#### Path Parameters
- None
#### Query Parameters
- None
#### Request Body
- **jsRuntime** (Microsoft.JSInterop.IJSRuntime) - Required - JavaScript runtime instance
### Request Example (Program.cs)
```csharp
builder.Services.AddCentrifugeClient(); // If using DI
// or manually:
var jsRuntime = /* get IJSRuntime instance */;
CentrifugeClient.InitializeBrowserInterop(jsRuntime);
```
### Response
- None (method returns void)
### Error Handling
- Not explicitly documented, but issues with `IJSRuntime` could cause failures.
```
--------------------------------
### Configure Centrifuge Client Options
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Set up advanced connection options for the Centrifuge client, including token management, connection data, client identification, reconnection settings, timeouts, logging, and custom headers. Use this for custom connection behaviors.
```csharp
var options = new CentrifugeClientOptions
{
// Connection token and refresh
Token = "your-jwt-token",
GetToken = async () => await FetchTokenAsync(),
// Connection data
Data = Encoding.UTF8.GetBytes("{\"custom\":\"data\"}"),
// Client identification (used for observability)
Name = "my-app",
Version = "1.0.0",
// Reconnection settings
MinReconnectDelay = TimeSpan.FromMilliseconds(500),
MaxReconnectDelay = TimeSpan.FromSeconds(20),
// Timeouts
Timeout = TimeSpan.FromSeconds(5),
MaxServerPingDelay = TimeSpan.FromSeconds(10),
// Logging (pass ILogger for debug output)
Logger = loggerFactory.CreateLogger(),
// Custom headers (works over header emulation, requires Centrifugo v6+)
Headers = new Dictionary
{
["X-Custom-Header"] = "value"
}
};
var client = new CentrifugeClient("ws://localhost:8000/connection/websocket", options);
```
--------------------------------
### Command Batching in Centrifuge C# SDK
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/README.md
Demonstrates sequential vs. batched command execution. Use batched commands for improved network efficiency, especially with HTTP transports. Batches are automatically managed with a 1ms delay and flushed if they exceed 15KB.
```csharp
// ❌ Sequential (no batching)
await subscription.PublishAsync(data1);
await subscription.PublishAsync(data2);
await subscription.PresenceAsync();
// Result: 3 separate network requests
// ✅ Batched (recommended)
var task1 = subscription.PublishAsync(data1);
var task2 = subscription.PublishAsync(data2);
var task3 = subscription.PresenceAsync();
await Task.WhenAll(task1, task2, task3);
// Result: 1 network request with all 3 commands!
```
--------------------------------
### Connect to Centrifuge Server
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/README.md
Initiates a connection to the Centrifuge server and waits for the client to be ready. Ensure the client is properly configured before calling Connect.
```csharp
client.Connect();
await client.ReadyAsync();
```
--------------------------------
### Handle CentrifugeTimeoutException
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/exceptions.md
Demonstrates how to catch a CentrifugeTimeoutException when calling ReadyAsync with a custom timeout. It also shows how to configure a default timeout for all client operations using CentrifugeClientOptions.
```csharp
try
{
await client.ReadyAsync(timeout: TimeSpan.FromSeconds(15));
}
catch (CentrifugeTimeoutException)
{
Console.WriteLine("Connection took too long");
}
// Or with custom timeout per operation
var options = new CentrifugeClientOptions
{
Timeout = TimeSpan.FromSeconds(10)
};
```
--------------------------------
### Handle CentrifugeGetStateException
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/exceptions.md
Illustrates setting up a custom GetState callback for a subscription, including error handling within the callback and listening for the subscription's Error event to catch state loading failures. The SDK automatically retries with backoff and fires an Error event if the GetState callback fails.
```csharp
var options = new CentrifugeSubscriptionOptions
{
GetState = async (channel) =>
{
try
{
return await database.GetPositionAsync(channel);
}
catch (Exception ex)
{
Console.WriteLine($"GetState failed: {ex.Message}");
throw; // SDK wraps this as CentrifugeGetStateException
}
}
};
subscription.Error += (sender, e) =>
{
if (e.Type == "getState")
{
Console.WriteLine($"State loading failed: {e.Message}");
}
};
```
--------------------------------
### Set Pre-release Version in .csproj
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/PUBLISHING.md
Defines a pre-release version for the NuGet package, such as a beta or release candidate, by appending the pre-release tag to the version number in the .csproj file.
```xml
1.1.0-beta.1
```
--------------------------------
### Create a Feature Branch
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/CONTRIBUTING.md
Create a new branch for your feature or bug fix.
```bash
git checkout -b feature/your-feature-name
```
--------------------------------
### CentrifugeClient - Core API
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/README.md
The `CentrifugeClient` class is the main entry point for interacting with the Centrifuge server. It handles connection management, subscription creation, and server communication.
```APIDOC
## CentrifugeClient
### Description
Provides the main entry point for the Centrifuge client library, managing connections, subscriptions, and server interactions.
### Methods
- **Connect()**: Establishes a connection to the Centrifuge server.
- **Disconnect()**: Closes the connection to the Centrifuge server.
- **ReadyAsync()**: Asynchronously waits until the client is ready.
- **NewSubscription(string channel)**: Creates a new subscription for the specified channel.
- **Publish(string channel, byte[] data)**: Publishes data to a channel.
- **Rpc(string method, byte[] data)**: Invokes a server-side RPC method.
### Events
- **Connected**: Fired when the client successfully connects.
- **Disconnected**: Fired when the client disconnects.
- **Error**: Fired when an error occurs.
```
--------------------------------
### Configure Client Identification Options
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/advanced-patterns.md
Specify client name and version for server-side identification. This helps in distinguishing different client applications connecting to the server.
```csharp
var options = new CentrifugeClientOptions
{
Name = "mobile-app", // Identifies where client connects from
Version = "2.1.0" // App version
};
var client = new CentrifugeClient(endpoint, options);
```
--------------------------------
### Safe Async Disposal with await using
Source: https://github.com/centrifugal/centrifuge-csharp/blob/main/_autodocs/advanced-patterns.md
Use `await using` for automatic and safe asynchronous disposal of the Centrifuge client, ensuring resources are released properly.
```csharp
await using var client = new CentrifugeClient("ws://localhost:8000/connection/websocket");
client.Connected += (sender, e) =>
{
Console.WriteLine($"Connected: {e.ClientId}");
};
client.Disconnected += (sender, e) =>
{
Console.WriteLine($"Disconnected: {e.Code} - {e.Reason}");
};
client.Connect();
await client.ReadyAsync();
// Use client...
// Automatic DisposeAsync called here
```