2

I got a basic Web Application with ASP.Net Core, where I initialized my SignalR hub.

The hub looks like this:

internal class SignalRTransceiverServer : Hub<ITransceiver<DataRecord, List<DataRecord>>>, ITransmitter<DataRecord>
{
    public async Task SendDataPackage(DataRecord package)
    {
        Console.WriteLine(package);
        try
        {
            await Clients.All.GetDataPackage(new List<DataRecord>() { package });
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

The interface ITransceiver looks like that:

public  interface ITransceiver<T, R> : IReceiver<R>, ITransmitter<T>
{
}

While the IReceiver has an event, which should get fired (for the client side application), when new data arrives:

public interface IReceiver<T>
{
    /// <summary>
    /// Gets a data package of <typeparamref name="T"/>. The parameter is for API's, which pass the arguments directly
    /// (via RPC e.g.) into the method. Invokes the DataReceived event.
    /// </summary>
    /// <param name="package">An optional package parameter, if the underlaying mechanism needs to pass the data directly into
    /// the function.</param>
    public Task GetDataPackage(T? package);
    public event EventHandler<T> DataReceived;  
}

Now when I try to call the GetDataPackage method via RPC on the hub it throws the following error:

Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher[8]
      Failed to invoke hub method 'SendDataPackage'.
      System.InvalidOperationException: Type must not contain events.
         at Microsoft.AspNetCore.SignalR.Internal.TypedClientBuilder`1.VerifyInterface(Type interfaceType)
         at Microsoft.AspNetCore.SignalR.Internal.TypedClientBuilder`1.VerifyInterface(Type interfaceType)
         at Microsoft.AspNetCore.SignalR.Internal.TypedClientBuilder`1.GenerateClientBuilder()
         at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
      --- End of stack trace from previous location ---
         at System.Lazy`1.CreateValue()
         at Microsoft.AspNetCore.SignalR.Internal.TypedClientBuilder`1.Build(IClientProxy proxy)
         at TestHub.SignalRTransceiverServer.SendDataPackage(DataRecord package) in D:\dat.eE\Praktikum.RH\TestHub\SignalRTransceiverServer.cs:line 25
         at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.ExecuteMethod(ObjectMethodExecutor methodExecutor, Hub hub, Object[] arguments)
         at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.<Invoke>g__ExecuteInvocation|18_0(DefaultHubDispatcher`1 dispatcher, ObjectMethodExecutor methodExecutor, THub hub, Object[] arguments, AsyncServiceScope scope, IHubActivator`1 hubActivator, HubConnectionContext connection, HubMethodInvocationMessage hubMethodInvocationMessage, Boolean isStreamCall)

I mean I understand this error (just get rid of the event in IReceiver), but why does SignalR Core not allow events in the targeted type? And how can I bypass it, while still using an event, if thats possible somehow?

2
  • sorry I can't understand your issue well based on the description and your code snippet. It like like you had an interface to encapsulate the Hub and you want to handle the DataReceived event. Per my understanding, we could directly handle the DataReceived received event in the data handling method. Pls correct me if I misunderstood your concerns. Commented Apr 23, 2024 at 2:01
  • The ITransmitter Interface is there, so the Client side always knows which method is has to call. The problem was, that the Client has the IReceiver Interface, which has the event and with hard types hubs the hubs could not send a message package to the client, because it had an event. That was my question, why it is not possible with hard typed hubs. Commented Apr 30, 2024 at 8:34

1 Answer 1

1

I figured out the easist workaround: just use the normal Hub class.

Instead of:

internal class SignalRTransceiverServer : Hub<ITransceiver<DataRecord, List<DataRecord>>>, ITransmitter<DataRecord>

And the specific RPC call with the specific method:

await Clients.All.GetDataPackage(new List<DataRecord>() { package });

I now use:

internal class SignalRTransceiverServer : Hub, ITransmitter<DataRecord>

which results in an RPC like that:

await Clients.All.SendAsync("GetDataPackage", new List<DataRecord>() { package });

Still the question, why it is like that, remains.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.