Shaunebu.SignalRManager.HubGenerator 1.0.3

dotnet add package Shaunebu.SignalRManager.HubGenerator --version 1.0.3
                    
NuGet\Install-Package Shaunebu.SignalRManager.HubGenerator -Version 1.0.3
                    
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.3">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
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.3" />
                    
Directory.Packages.props
<PackageReference Include="Shaunebu.SignalRManager.HubGenerator">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
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.3
                    
#r "nuget: Shaunebu.SignalRManager.HubGenerator, 1.0.3"
                    
#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.3
                    
#: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.3
                    
Install as a Cake Addin
#tool nuget:?package=Shaunebu.SignalRManager.HubGenerator&version=1.0.3
                    
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

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • No dependencies.

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 142 10/31/2025
1.0.2 133 10/31/2025
1.0.1 133 10/31/2025
1.0.0 136 10/31/2025