SignalR .NET Client Invoke throws an exception
Asked Answered
A

3

3

I'm trying to get a console application working with the SignalR .Net Client but I'm getting an error when I try to invoke a method on the Hub. Here's my code for the console app:

static void Main(string[] args)
{            
    var connection = new HubConnection("http://localhost/SignalRTest");
    var myHub = connection.CreateProxy("SignalRTest.Classes.service");

    myHub.On<string>("addMessage", text =>
    {
        Console.WriteLine(text);
    });

    connection.Start().ContinueWith(task =>
    {
        if (task.IsFaulted)
        {   
            Console.WriteLine("There was an error opening the connection: {0}", task.Exception.GetBaseException());
        }
        else {                        
            Console.WriteLine("Connected.");
        }
   }).Wait();


   myHub.Invoke("Send", "Message from console.").ContinueWith(task => {
       if (task.IsFaulted)
       {                
           Console.WriteLine("There was an error calling Send: {0}", task.Exception.GetBaseException());
       }
       else
       {
           Console.WriteLine("Send complete.");
       }

   });


   Console.ReadLine();

}

Here is the Hub from the Server:

[HubName("service")]
public class ServiceHub : Hub
{
    public void Send(string message)
    {
        // Call the addMessage method on all clients
        Clients.addMessage(message);
    }
}

I assume that the console app is connecting correctly because it writes out "Connected." But when it tries to call the Send method on the server, I get the following error:

System.Net.WebException: The remote server returned an error: (500) Internal Server Error. at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) at SignalR.HttpHelper.<>c_DisplayClass2.b_0(IAsyncResult ar) at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func2 endMethod, TaskCompletionSource`1 tcs)

Can anyone tell me what I'm doing wrong? Thanks.

Asturias answered 12/3, 2012 at 2:28 Comment(0)
G
4

This issue appears to be caused by using an invalid hub name (when using CreateProxy). It is strange that the start method doesn't fail but i just tested this and got the same behavior as you using a non-existent hub name.

Goutweed answered 13/3, 2012 at 4:30 Comment(5)
That worked. Thanks! I thought that I could change the hub name with this [HubName("service")]. It worked on the javascript client but not on the console client. But that doesn't really matter right now because I didn't need it. Thanks again for your help. I can't believe I was that close.Asturias
@jmac, so you changed var myHub = connection.CreateProxy("SignalRTest.Classes.service"); to var myHub = connection.CreateProxy("service"); or did you remove attribute [HubName("service")] ?Sells
@PrerakK keeping in mind that this was almost two years ago now. The issue would have been var myHub = connection.CreateProxy("service"). This was wrong as the hubname attribute only effects the generated javascript and not the actual endpoint. The correct line would be var myHub = connection.CreateProxy("ServiceHub")Goutweed
@Gary, thanks for reverting back. I appreciate. I just made a hub and attributed it like [HubName("chat")]public class ChatHub : Hub{...} and while in windows store application accessed it with chatProxy = hubConnection.CreateHubProxy("chat"); and it worked fine. My be there were changes to libraries in these two year. Thanks again.Sells
@Gary, I think missed a point ..the methods I am using Is "CreateHubProxy" so definitely the library has changed. thanksSells
G
0

You have not added the SignalR.hosting.AspNet dll, so this error is created. So, first include the dll with SignalR.Hosting.AspNet on the server.

Giff answered 8/5, 2012 at 10:22 Comment(0)
W
0

For me this was a result of my SignalR hub requiring a dependency injection parameter. The error gets quite well hidden, even with the ShowDetailedErrors being set to true it was obscured except within the Server logs of Azure.

The error you get is something like this:

System.MissingMethodException:
   at System.RuntimeTypeHandle.CreateInstance (mscorlib, Version=4.0.0.0, 
   Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.RuntimeType.CreateInstanceSlow (mscorlib, Version=4.0.0.0, 
   Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.RuntimeType.CreateInstanceDefaultCtor (mscorlib, Version=4.0.0.0, 
   at Microsoft.AspNet.SignalR.Hubs.DefaultHubActivator.Create 
   (Microsoft.AspNet.SignalR.Core, Version=2.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)

As you can see I was using the 'DefaultHubActivator' which doesn't know how to manage injector parameters. So I followed this fine advice which taught me how to do the injection using Unity.

The basics are you need to write your own hub activator, but you can inherit from the default one and just extend it to avoid having to register the dozens of dependencies that SignalR has.

 public class SignalRUnityDependencyResolver : DefaultDependencyResolver
{
    private readonly IUnityContainer _container;
    public SignalRUnityDependencyResolver(IUnityContainer container)
    {
        _container = container ?? throw new ArgumentNullException(nameof(container));
    }

    public override object GetService(Type serviceType)
    {
        return _container.IsRegistered(serviceType) ? _container.Resolve(serviceType) : base.GetService(serviceType);
    }

    public override IEnumerable<object> GetServices(Type serviceType)
    {
        return _container.IsRegistered(serviceType) ? _container.ResolveAll(serviceType) : base.GetServices(serviceType);
    }
}

After which you set it up in your Startup

app.Map("/signalr", map =>
        {
            var hubConfiguration = new HubConfiguration()
            {
                EnableJSONP = true,
                EnableDetailedErrors = true,
                Resolver = new SignalRUnityDependencyResolver(UnityConfig.GetContainer())
            };
            map.RunSignalR(hubConfiguration);
            logger.WriteInfo("Started signalr.");
        });

Finally registering your hub with Unity

container.RegisterType<MyHub>(new InjectionFactory((obj) => new MyHub(obj.Resolve<ILogger>())));
Winters answered 21/6, 2018 at 9:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.