Shaunebu.Common.SignalRManager
1.0.0
dotnet add package Shaunebu.Common.SignalRManager --version 1.0.0
NuGet\Install-Package Shaunebu.Common.SignalRManager -Version 1.0.0
<PackageReference Include="Shaunebu.Common.SignalRManager" Version="1.0.0" />
<PackageVersion Include="Shaunebu.Common.SignalRManager" Version="1.0.0" />
<PackageReference Include="Shaunebu.Common.SignalRManager" />
paket add Shaunebu.Common.SignalRManager --version 1.0.0
#r "nuget: Shaunebu.Common.SignalRManager, 1.0.0"
#:package Shaunebu.Common.SignalRManager@1.0.0
#addin nuget:?package=Shaunebu.Common.SignalRManager&version=1.0.0
#tool nuget:?package=Shaunebu.Common.SignalRManager&version=1.0.0
A comprehensive, enterprise-grade SignalR client library for .NET that provides robust connection management, advanced resilience patterns, and production-ready observability.
✨ Features
🔌 Connection Management
Automatic Reconnection - Handles transient failures gracefully
Connection State Tracking - Real-time state monitoring with events
Configurable Timeouts - Customizable connection and handshake timeouts
Multi-Transport Support - WebSockets, Server-Sent Events, Long Polling
📨 Message Processing
Intelligent Batching - Configurable batch sizes and intervals
Priority Queuing - Priority-based message processing
Offline Queue - Message persistence during disconnections
Batch Processing - Efficient bulk message delivery
🛡️ Resilience & Reliability
Polly Integration - Advanced retry policies with exponential backoff
Circuit Breaker - Prevents cascade failures
Error Isolation - Handler errors don't break the system
Graceful Degradation - Maintains partial functionality during failures
📊 Observability
Comprehensive Metrics - Connection, message, and performance metrics
Structured Logging - Detailed logging with configurable levels
State Change Events - Real-time connection state notifications
Custom Exporters - Extensible metrics exporting
🔧 Developer Experience
Type-Safe Wrappers - Compile-time safety for hub methods
Fluent Configuration - Intuitive builder pattern setup
Dependency Injection - Seamless ASP.NET Core integration
Async/Await Support - Full asynchronous operation support
🚀 Quick Start
Installation
dotnet add package Shaunebu.SignalRManager
Basic Usage
// Create and configure the manager
var manager = new SignalRManagerBuilder()
.WithHubUrl("https://api.example.com/hubs/chat")
.WithBatching(batchSize: 20, batchInterval: TimeSpan.FromMilliseconds(250))
.WithPollyRetryPolicy(maxRetries: 5)
.WithMetricsExporter(new ConsoleMetricsExporter())
.WithAutoReconnect(enabled: true, maxAttempts: 3)
.Build();
// Initialize connection
await manager.InitializeAsync();
// Register message handlers
manager.RegisterHandler<string, string>("ReceiveMessage",
(user, message) => Console.WriteLine($"{user}: {message}"));
// Send messages
await manager.InvokeAsync("SendMessage", new object[] { "John", "Hello World!" });
// Clean shutdown
await manager.ShutdownAsync();
📖 Comprehensive Examples
Type-Safe Hub Clients
// Create type-safe client wrapper
public class ChatHubClient
{
private readonly ISignalRManager _manager;
public ChatHubClient(ISignalRManager manager) => _manager = manager;
public Task SendMessageAsync(string user, string message) =>
_manager.InvokeAsync<object>("SendMessage", new object[] { user, message });
public IDisposable OnMessageReceived(Action<string, string> handler) =>
_manager.RegisterHandler<string, string>("ReceiveMessage", handler);
}
// Usage
var chatClient = new ChatHubClient(manager);
await chatClient.SendMessageAsync("Alice", "Hello from type-safe client!");
chatClient.OnMessageReceived((user, msg) => Console.WriteLine($"{user}: {msg}"));
Advanced Configuration
var manager = new SignalRManagerBuilder()
.WithHubUrl("https://api.example.com/hubs/notifications")
// Resilience
.WithPollyRetryPolicy(
maxRetries: 5,
initialDelay: TimeSpan.FromSeconds(1),
maxDelay: TimeSpan.FromMinutes(2))
.WithCircuitBreakerPersistence(new RedisCircuitBreakerPersistence())
// Performance
.WithBatching(batchSize: 50, batchInterval: TimeSpan.FromMilliseconds(500))
.WithOfflineQueue(enabled: true)
// Security
.WithEncryptor(new AesEncryptor(key, iv))
.WithHeader("Authorization", "Bearer your-token")
// Observability
.WithMetricsExporter(new ApplicationInsightsMetricsExporter())
.WithLogger(logger)
// Advanced
.WithTransport(TransportType.WebSockets)
.WithTimeout(connectionTimeout: TimeSpan.FromSeconds(30))
.ConfigureConnection(builder =>
builder.WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.FromSeconds(2) }))
.Build();
ASP.NET Core Integration
// Program.cs
builder.Services.AddSignalRManager(options =>
{
options.HubUrl = "https://api.example.com/hubs/chat";
options.EnableBatching = true;
options.BatchSize = 20;
options.EnableOfflineQueue = true;
options.AutoReconnect = true;
})
.AddTypedHubClients(); // Optional: for type-safe clients
// Controller usage
public class NotificationController(ISignalRManager signalRManager)
{
[HttpPost]
public async Task<IActionResult> SendNotification([FromBody] NotificationRequest request)
{
await signalRManager.InvokeAsync("SendNotification", new object[] { request.Message });
return Ok();
}
}
🔧 Configuration Options
SignalRManagerOptions
| Property | Default | Description |
|---|---|---|
HubUrl |
Required | SignalR hub URL |
EnableBatching |
true |
Enable message batching |
BatchSize |
10 |
Maximum messages per batch |
BatchInterval |
250ms |
Maximum time to wait for batch |
EnableOfflineQueue |
true |
Persist messages when offline |
HeartbeatInterval |
30s |
Heartbeat check interval |
AutoReconnect |
true |
Automatic reconnection |
MaxReconnectAttempts |
5 |
Maximum reconnection attempts |
ConnectionTimeout |
30s |
Connection establishment timeout |
TransportType |
All |
Preferred transport type |
📊 Monitoring & Metrics
Built-in Metrics
public interface IMetricsExporter
{
void OnConnected(string connectionId);
void OnDisconnected(string? connectionId);
void OnReconnectAttempt(int attempt);
void OnMessageSent();
void OnMessageBatchProcessed(int batchSize);
void OnCircuitBreakerStateChange(CircuitBreakerState state);
void OnError(Exception exception, string operation);
}
Custom Metrics Exporter
public class CustomMetricsExporter : IMetricsExporter
{
public void OnConnected(string connectionId)
{
// Integrate with your monitoring system
Metrics.Increment("signalr.connections.active");
Logger.LogInformation("Client connected: {ConnectionId}", connectionId);
}
// Implement other methods...
}
🛡️ Resilience Patterns
Custom Retry Policy
public class CustomRetryPolicy : IRetryPolicy
{
public TimeSpan? NextDelay(int attempt, Exception? lastException)
{
if (IsFatalException(lastException)) return null;
return attempt switch
{
< 3 => TimeSpan.FromSeconds(1 * attempt),
< 5 => TimeSpan.FromSeconds(5),
_ => null // Stop retrying
};
}
private bool IsFatalException(Exception? ex) =>
ex is OperationCanceledException or ObjectDisposedException;
}
Circuit Breaker with Persistence
// Redis persistence example
public class RedisCircuitBreakerPersistence : ICircuitBreakerPersistence
{
private readonly IDatabase _redis;
public async Task<CircuitState?> LoadStateAsync(string circuitName) =>
await _redis.StringGetAsync($"circuitbreaker:{circuitName}");
public async Task SaveStateAsync(string circuitName, CircuitState state) =>
await _redis.StringSetAsync($"circuitbreaker:{circuitName}", state);
}
📊 Feature Comparison Table
| Feature | SignalRManager | Microsoft SignalR Client | Azure SignalR Service SDK | SignalR.Client.Core |
|---|---|---|---|---|
| Connection Management | ✅ Advanced | ✅ Basic | ✅ Managed | ✅ Basic |
| Automatic Reconnection | ✅ Configurable | ✅ Limited | ✅ Managed | ✅ Limited |
| Message Batching | ✅ Intelligent | ❌ None | ❌ None | ❌ None |
| Priority Queuing | ✅ Yes | ❌ No | ❌ No | ❌ No |
| Offline Queue | ✅ Persistent | ❌ No | ❌ No | ❌ No |
| Retry Policies | ✅ Polly + Custom | ✅ Basic | ✅ Basic | ✅ Basic |
| Circuit Breaker | ✅ Yes | ❌ No | ❌ No | ❌ No |
| State Persistence | ✅ Yes | ❌ No | ❌ No | ❌ No |
| Metrics & Telemetry | ✅ Comprehensive | ❌ Minimal | ✅ Limited | ❌ No |
| Type-Safe Wrappers | ✅ Yes | ❌ No | ❌ No | ❌ No |
| DI Integration | ✅ First-class | ✅ Basic | ✅ Basic | ✅ Basic |
| Configuration | ✅ Fluent API | ✅ Basic | ✅ Basic | ✅ Basic |
| Performance | ✅ Optimized | ✅ Good | ✅ Good | ✅ Good |
| Learning Curve | 🟡 Moderate | 🟢 Easy | 🟢 Easy | 🟢 E |
🔍 Troubleshooting
Common Issues
Connection Failures
// Enable detailed logging
var manager = new SignalRManagerBuilder()
.WithHubUrl("your-hub-url")
.WithLogger(LoggerFactory.Create(builder =>
builder.AddConsole().SetMinimumLevel(LogLevel.Debug)))
.Build();
Message Delivery Issues
// Monitor batch events
manager.OnMessageBatched += (method, count) =>
Console.WriteLine($"{count} messages batched for {method}");
// Check offline queue
manager.OnOfflineQueueSizeChanged += size =>
Console.WriteLine($"Offline queue size: {size}");
📈 Performance Tips
Batch Sizing: Adjust
BatchSizeandBatchIntervalbased on your throughput requirementsPriority Queuing: Use message priorities for critical messages
Connection Pooling: Reuse SignalRManager instances when possible
Memory Management: Monitor offline queue size in high-volume scenarios
📄 License
This project is licensed under the MIT License.
🏆 Acknowledgments
Built on top of Microsoft's SignalR Client
Resilience patterns inspired by Polly
Metrics design influenced by OpenTelemetry standards
<br><br>
🎯 Hub Generator - Type-Safe SignalR Development
⚡ Automatic Interface Generation
SignalRManager includes a powerful Source Generator that automatically creates strongly-typed interfaces for ALL classes that inherit from Hub, eliminating magic strings and providing compile-time safety.
🔧 How It Works
1. Simply Inherit from Hub (No Attributes Needed!)
// No attributes required! The generator automatically detects Hub classes
public class ChatHub : Hub
{
[ServerMethod]
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
[ServerMethod]
public Task JoinGroup(string groupName)
{
return Groups.AddToGroupAsync(Context.ConnectionId, groupName);
}
[ClientMethod]
private Task ReceiveMessage(string user, string message) => Task.CompletedTask;
[ClientMethod]
private Task UserJoined(string user) => Task.CompletedTask;
}
public class NotificationHub : Hub
{
[ServerMethod]
public Task SendNotification(string message)
{
return Clients.All.SendAsync("ReceiveNotification", message);
}
[ClientMethod]
private Task ReceiveNotification(string message) => Task.CompletedTask;
}
2. Generated Interfaces (Automatically Created)
IChatHubServer.g.cs (Server-side interface):
public interface IChatHubServer
{
Task SendMessage(string user, string message);
Task JoinGroup(string groupName);
}
IChatHubClient.g.cs (Client-side interface):
public interface IChatHubClient
{
Task ReceiveMessage(string user, string message);
Task UserJoined(string user);
}
INotificationHubServer.g.cs:
public interface INotificationHubServer
{
Task SendNotification(string message);
}
INotificationHubClient.g.cs:
public interface INotificationHubClient
{
Task ReceiveNotification(string message);
}
🚀 Usage with Generated Interfaces
Client-Side Usage
// Type-safe handler registration
await manager.RegisterHandler<IChatHubClient, string, string>(
c => c.ReceiveMessage,
async (user, msg) => Console.WriteLine($"{user}: {msg}"));
// Type-safe method invocation
await manager.InvokeAsync<IChatHubServer, string, string>(
s => s.SendMessage,
"John",
"Hello from type-safe client!");
// Multiple hubs support
await manager.RegisterHandler<INotificationHubClient, string>(
c => c.ReceiveNotification,
async (msg) => Console.WriteLine($"Notification: {msg}"));
Server-Side Usage (Optional)
// Implement the generated interface on your hub (optional)
public class ChatHub : Hub, IChatHubServer
{
public async Task SendMessage(string user, string message)
{
// Your implementation
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
public async Task JoinGroup(string groupName)
{
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
}
}
⚙️ Method Attributes
// Use these attributes to specify which methods to include
[ServerMethod] // Marks hub methods callable by clients (REQUIRED)
[ClientMethod] // Marks client methods callable by server (REQUIRED)
// Examples:
public class ChatHub : Hub
{
[ServerMethod] // This method can be called by clients
public Task SendMessage(string user, string message)
=> Clients.All.SendAsync("ReceiveMessage", user, message);
[ClientMethod] // This method can be called by server on clients
private Task ReceiveMessage(string user, string message) => Task.CompletedTask;
}
🎯 Benefits of Hub Generator
1. Zero Configuration
✅ Automatically detects ALL
Hubclasses✅ No attributes needed on classes
✅ Generates interfaces at compile time
2. Compile-Time Safety
// ✅ Compiles - type-safe
await manager.InvokeAsync<IChatHubServer, string, string>(
s => s.SendMessage, "user", "message");
// ❌ Compile error - method doesn't exist
await manager.InvokeAsync<IChatHubServer, string, string>(
s => s.NonExistentMethod, "user", "message"); // ERROR!
3. IntelliSense Support
✅ Full IntelliSense for hub methods
✅ Parameter type checking
✅ Method discovery
4. Refactoring Friendly
✅ Rename hub methods safely
✅ Change parameters with compile-time checks
✅ Find all references works perfectly
🔧 Setup Requirements
1. Add to Your Project
<PackageReference Include="Shaunebu.SignalRManager.HubGenerator" Version="1.0.0" />
2. Enable in Project File
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
📁 Generated Files Location
Generated interfaces are created in:
/bin/Debug/net8.0/Generated/Shaunebu.SignalRManager.HubGenerator/
- IChatHubClient.g.cs
- IChatHubServer.g.cs
- INotificationHubClient.g.cs
- INotificationHubServer.g.cs
🚀 Advanced Usage
Multiple Hubs Project
// All hubs are automatically processed
public class ChatHub : Hub { /* ... */ }
public class NotificationHub : Hub { /* ... */ }
public class AdminHub : Hub { /* ... */ }
public class AnalyticsHub : Hub { /* ... */ }
// All interfaces are generated automatically:
// IChatHubClient, IChatHubServer
// INotificationHubClient, INotificationHubServer
// IAdminHubClient, IAdminHubServer
// IAnalyticsHubClient, IAnalyticsHubServer
Custom Method Filtering
public class SecureHub : Hub
{
[ServerMethod]
public Task PublicMethod(string data) { /* ... */ }
// This won't be included in the interface (no attribute)
public Task InternalMethod(string data) { /* ... */ }
[ClientMethod]
private Task ClientCallback(string result) => Task.CompletedTask;
}
The Hub Generator transforms SignalR development from string-based magic to type-safe, compiler-verified code, making your SignalR applications more maintainable and less error-prone! 🎯
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.AspNetCore.SignalR.Client (>= 9.0.9)
- Microsoft.Extensions.Logging (>= 9.0.9)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.9)
- Newtonsoft.Json (>= 13.0.4)
- Oakrey.ReactiveExtensions (>= 2.1.1)
- Polly (>= 8.6.4)
- Polly.Core (>= 8.6.4)
- YamlDotNet (>= 16.3.0)
-
net8.0
- Microsoft.AspNetCore.SignalR.Client (>= 9.0.9)
- Microsoft.Extensions.Logging (>= 9.0.9)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.9)
- Newtonsoft.Json (>= 13.0.4)
- Oakrey.ReactiveExtensions (>= 2.1.1)
- Polly (>= 8.6.4)
- Polly.Core (>= 8.6.4)
- System.Threading.Channels (>= 9.0.9)
- YamlDotNet (>= 16.3.0)
-
net9.0
- Microsoft.AspNetCore.SignalR.Client (>= 9.0.9)
- Microsoft.Extensions.Logging (>= 9.0.9)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.9)
- Newtonsoft.Json (>= 13.0.4)
- Oakrey.ReactiveExtensions (>= 2.1.1)
- Polly (>= 8.6.4)
- Polly.Core (>= 8.6.4)
- YamlDotNet (>= 16.3.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 185 | 10/31/2025 |