Shaunebu.SignalRManager.HubGenerator 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Shaunebu.SignalRManager.HubGenerator --version 1.0.0
                    
NuGet\Install-Package Shaunebu.SignalRManager.HubGenerator -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Shaunebu.SignalRManager.HubGenerator" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Shaunebu.SignalRManager.HubGenerator" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Shaunebu.SignalRManager.HubGenerator" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Shaunebu.SignalRManager.HubGenerator --version 1.0.0
                    
#r "nuget: Shaunebu.SignalRManager.HubGenerator, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Shaunebu.SignalRManager.HubGenerator@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Shaunebu.SignalRManager.HubGenerator&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Shaunebu.SignalRManager.HubGenerator&version=1.0.0
                    
Install as a Cake Tool

A powerful Roslyn Source Generator that automatically creates strongly-typed interfaces for your SignalR hubs, eliminating magic strings and providing compile-time safety for both client and server development.

NuGet Version

NET Support NET Support NET Support Support

https://img.shields.io/badge/SourceGenerator-Yes-green

✨ Features

🎯 Automatic Interface Generation

  • Zero Configuration - Automatically detects all classes inheriting from Hub

  • Dual Interfaces - Generates both client and server interfaces

  • Compile-Time Safety - Eliminates runtime errors from magic strings

  • IntelliSense Support - Full IDE support with parameter checking

🔧 Smart Method Discovery

  • Attribute-Based Filtering - Use [ServerMethod] and [ClientMethod] attributes

  • Flexible Method Selection - Choose which methods to include in interfaces

  • Private Method Support - Include private methods for client callbacks

🚀 Seamless Integration

  • No Runtime Dependencies - Pure compile-time generation

  • Works with Any SignalR Hub - Compatible with existing hubs

  • Fast Compilation - Minimal impact on build times

  • Debugging Support - View generated files for troubleshooting

🚀 Quick Start

Installation

dotnet add package Shaunebu.SignalRManager.HubGenerator

Basic Usage

1. Create Your Hub Class
using Microsoft.AspNetCore.SignalR;
using Shaunebu.SignalR.HubGenerator;

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;
}
2. Generated Interfaces (Automatically)

IChatHubServer.g.cs (Server-side interface):

using System.Threading.Tasks;

namespace Generated.Hubs
{
    public interface IChatHubServer
    {
        Task SendMessage(string user, string message);
        Task JoinGroup(string groupName);
    }
}

IChatHubClient.g.cs (Client-side interface):

using System.Threading.Tasks;

namespace Generated.Hubs
{
    public interface IChatHubClient
    {
        Task ReceiveMessage(string user, string message);
        Task UserJoined(string user);
    }
}
3. Use Generated Interfaces

Client-Side (Type-Safe):

// Type-safe handler registration
await signalRManager.RegisterHandler<IChatHubClient, string, string>(
    c => c.ReceiveMessage,
    async (user, msg) => Console.WriteLine($"{user}: {msg}"));

// Type-safe method invocation  
await signalRManager.InvokeAsync<IChatHubServer, string, string>(
    s => s.SendMessage,
    "John", "Hello World!");

// Type-safe group operations
await signalRManager.InvokeAsync<IChatHubServer, string>(
    s => s.JoinGroup, 
    "general");

Server-Side (Optional):

// Implement the generated interface for additional type safety
public class ChatHub : Hub, IChatHubServer
{
    public async Task SendMessage(string user, string message)
    {
        // Compile-time checked implementation
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
    
    public async Task JoinGroup(string groupName)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
    }
}

📖 Comprehensive Examples

Multiple Hubs Setup

// ChatHub.cs
public class ChatHub : Hub
{
    [ServerMethod]
    public Task SendMessage(string user, string message) 
        => Clients.All.SendAsync("ReceiveMessage", user, message);
    
    [ServerMethod]
    public Task TypingNotification(string user, bool isTyping)
        => Clients.Others.SendAsync("UserTyping", user, isTyping);
    
    [ClientMethod]
    private Task ReceiveMessage(string user, string message) => Task.CompletedTask;
    
    [ClientMethod]
    private Task UserTyping(string user, bool isTyping) => Task.CompletedTask;
}

// NotificationHub.cs  
public class NotificationHub : Hub
{
    [ServerMethod]
    public Task BroadcastNotification(string title, string message, string type)
        => Clients.All.SendAsync("ReceiveNotification", title, message, type);
    
    [ServerMethod]
    public Task SendToUser(string userId, string message)
        => Clients.User(userId).SendAsync("ReceivePersonalNotification", message);
    
    [ClientMethod]
    private Task ReceiveNotification(string title, string message, string type) => Task.CompletedTask;
    
    [ClientMethod]
    private Task ReceivePersonalNotification(string message) => Task.CompletedTask;
}

Advanced Method Configuration

public class AdvancedHub : Hub
{
    // Server methods (callable by clients)
    [ServerMethod]
    public Task<string> GetDataWithReturn(string filter) 
    {
        return Task.FromResult($"Filtered: {filter}");
    }
    
    [ServerMethod]
    public Task ProcessData(string data, int priority, bool urgent)
    {
        return Clients.Caller.SendAsync("ProcessingComplete", $"Processed: {data}");
    }
    
    // Client methods (callable by server)
    [ClientMethod]
    private Task DataReceived(string result) => Task.CompletedTask;
    
    [ClientMethod] 
    private Task ProcessingComplete(string message) => Task.CompletedTask;
    
    // This method won't be included in interfaces (no attribute)
    public Task InternalMethod() => Task.CompletedTask;
}

⚙️ Configuration

Method Attributes

// Use these attributes to control which methods are included

[ServerMethod]  // Includes method in server interface (callable by clients)
[ClientMethod]  // Includes method in client interface (callable by server)

// Examples:
public class ExampleHub : Hub
{
    [ServerMethod]
    public Task ServerSideMethod(string param) { /* ... */ }
    
    [ClientMethod] 
    private Task ClientSideMethod(string result) => Task.CompletedTask;
    
    // No attribute = not included in generated interfaces
    public Task InternalMethod() { /* ... */ }
}

Project Configuration (Optional)

For debugging generated files, add to your .csproj:

<PropertyGroup>
  <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
  <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

🎯 Benefits

1. 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!

// ❌ Compile error - wrong parameter types
await manager.InvokeAsync<IChatHubServer, int, string>(
    s => s.SendMessage, 123, "message"); // ERROR!

2. Refactoring Support

  • ✅ Rename methods safely with full reference updates

  • ✅ Change parameters with compile-time validation

  • ✅ Find all references works across client and server

  • ✅ Safe deletions with immediate compile errors

3. IntelliSense & Discovery

  • ✅ Full method completion in IDE

  • ✅ Parameter type hints and documentation

  • ✅ Method discovery without checking hub source

  • ✅ Navigation between interface and implementation

🔧 Advanced Usage

Complex Parameter Types

public class DataHub : Hub
{
    [ServerMethod]
    public Task ProcessUserData(UserData user, DataFilter filter)
        => Clients.Caller.SendAsync("DataProcessed", new ProcessResult());
    
    [ClientMethod]
    private Task DataProcessed(ProcessResult result) => Task.CompletedTask;
}

// Generated interfaces handle complex types:
public interface IDataHubServer
{
    Task ProcessUserData(UserData user, DataFilter filter);
}

public interface IDataHubClient  
{
    Task DataProcessed(ProcessResult result);
}

Async Method Support

public class AsyncHub : Hub
{
    [ServerMethod]
    public async Task<string> LongRunningOperationAsync(string input)
    {
        await Task.Delay(1000);
        return $"Processed: {input}";
    }
    
    [ClientMethod]
    private async Task OperationCompletedAsync(string result) 
    {
        await SomeProcessing(result);
    }
}

📊 Generated Files Structure

YourProject/
├── bin/
│   └── Debug/
│       └── net8.0/
│           └── generated/
│               └── Shaunebu.SignalRManager.HubGenerator/
│                   ├── IChatHubClient.g.cs
│                   ├── IChatHubServer.g.cs
│                   ├── INotificationHubClient.g.cs
│                   ├── INotificationHubServer.g.cs
│                   └── ...
└── ...

🛠️ Troubleshooting

Common Issues

1. Interfaces Not Generated

  • Ensure your class inherits from Hub

  • Check that methods have [ServerMethod] or [ClientMethod] attributes

  • Verify the NuGet package is installed

2. Compilation Errors

  • Check method parameter types match between hub and usage

  • Ensure all referenced types are accessible

  • Verify async methods return Task or Task<T>

3. Debugging Generated Code


<PropertyGroup>
  <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>

Verification Steps

  1. Check Installation: Ensure package is referenced in your project

  2. Build Project: Generated interfaces appear after first build

  3. Verify Attributes: Methods should have [ServerMethod] or [ClientMethod]

  4. Check Output: Look for generated files in output directory

🤝 Integration with SignalRManager

Perfect Companion

This generator works seamlessly with SignalRManager:

var manager = new SignalRManagerBuilder()
    .WithHubUrl("https://api.example.com/hubs/chat")
    .Build();

await manager.InitializeAsync();

// Use generated interfaces for type safety
await manager.RegisterHandler<IChatHubClient, string, string>(
    c => c.ReceiveMessage,
    (user, msg) => Console.WriteLine($"{user}: {msg}"));

await manager.InvokeAsync<IChatHubServer, string, string>(
    s => s.SendMessage, 
    "Alice", "Hello from type-safe client!");

🏆 Acknowledgments

  • Built with Roslyn Source Generators

  • Inspired by the need for type-safe SignalR development

  • Part of the SignalRManager ecosystem

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.3 172 10/31/2025
1.0.2 152 10/31/2025
1.0.1 152 10/31/2025
1.0.0 164 10/31/2025