### 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 ```