5

I am using this example from https://blogs.msdn.microsoft.com/webdev/2017/09/14/announcing-signalr-for-asp-net-core-2-0/ to create a console app that can send messages from a simple console app to a web page.

Below is the simple example for console application which reads the user input and prints that input on the screen, I want to send the same user input also to the web page.

static void Main(string[] args)
        {
            while (true)
            {
                Console.WriteLine("Enter input:");
                string line = Console.ReadLine();
                if (line == "exit")
                {
                    break;
                }
                sendSignalToClient(line);
                Console.Write("Message Sent To Client: " + line);
            }
        }

        private static void sendSignalToClient(string line)
        {
            //Send a message from this app to web client using signalR
        }

I have just started learning about this. Any material or suggestions related to this is appreciated. -Thanks

Edit: I am using a sample signalR chat application.

public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }

public class ChatHub : Hub
    {
        public void Send(string name, string message)
        {
            // Call the broadcastMessage method to update clients.
            Clients.All.InvokeAsync("broadcastMessage", name, message);
        }
    }

public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSignalR();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseFileServer();

            app.UseSignalR(routes =>
            {
                routes.MapHub<ChatHub>("chat");
            });
        }

Below is the code for the console application that is sending messages to web page

class Program : Hub
{
    static void Main(string[] args)
    {
        Task.Run(Run).Wait();
    }

    static async Task Run()
    {
        var connection = new HubConnectionBuilder()
            .WithUrl("http://localhost:59768/chat")
            .WithConsoleLogger()
            .WithMessagePackProtocol()
            .WithTransport(TransportType.WebSockets)
            .Build();

        await connection.StartAsync();

        Console.WriteLine("Starting connection. Press Ctrl-C to close.");
        var cts = new CancellationTokenSource();
        Console.CancelKeyPress += (sender, a) =>
        {
            a.Cancel = true;
            cts.Cancel();
        };

        connection.Closed += e =>
        {
            Console.WriteLine("Connection closed with error: {0}", e);

            cts.Cancel();
            return Task.CompletedTask;
        };

        connection.On("broadcastMessage", async () =>
        {


        });

        while (true)
        {
            Thread.Sleep(2000);

            await connection.SendAsync("send", "alex", "hello");

        }
    }

All the code is working but on the console application i am receiving this exception:

 Microsoft.AspNetCore.Sockets.Client.HttpConnection[19]
      09/17/2017 13:47:17: Connection Id 40da6d4b-9c47-4831-802f-628bbb172e10: An exception was thrown from the 'Received' event handler.
System.FormatException: Target method expects 0 arguments(s) but invocation has 2 argument(s).
   at Microsoft.AspNetCore.SignalR.Internal.Protocol.MessagePackHubProtocol.CreateInvocationMessage(Unpacker unpacker, IInvocationBinder binder)
   at Microsoft.AspNetCore.SignalR.Internal.Protocol.MessagePackHubProtocol.TryParseMessages(ReadOnlyBuffer`1 input, IInvocationBinder binder, IList`1& messages)
   at Microsoft.AspNetCore.SignalR.Internal.HubProtocolReaderWriter.ReadMessages(Byte[] input, IInvocationBinder binder, IList`1& messages)
   at Microsoft.AspNetCore.SignalR.Client.HubConnection.<OnDataReceivedAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Sockets.Client.HttpConnection.<>c__DisplayClass49_0.<<ReceiveAsync>b__0>d.MoveNext()
Alexander
  • 91
  • 1
  • 10

2 Answers2

5

Your event handler should take a string argument, it should look like this:

connection.On<string>("broadcastMessage", data =>
{

});
davidfowl
  • 37,120
  • 7
  • 93
  • 103
3

Take a look at this tutorial because although it is bit old it would give you good advices:

https://learn.microsoft.com/en-us/aspnet/signalr/overview/getting-started/tutorial-getting-started-with-signalr

On the one hand you web page needs to connect to a SignalR Hub and on the other your console should connect to a service, probably in you web project, to send the message to the hub and from there to all the registered clients. The key is that the hub executes JavaScript functions in client side but it has to know the clients, due to a registration, and that hub instance had to be called to execute is methods. What makes me sense is to inject the hub in an API controller and, using httpclient, post the inputs to your controller.

Another good tutorial but this one is very recent:

https://spontifixus.github.io/ASPNET-Core-SignalR-with-Aurelia-and-Webpack/

I hope it helps.

Juan

EDIT:

I've just found an answer (may 2017) to the same question here:

SignalR Console app example

In server side:

 [HubName("MyHub")]
        public class MyHub : Hub
        {
            public void Send(string name, string message)
            {
                Clients.All.addMessage(name, message);
            }
        }

And in client side:

 var myHub = connection.CreateHubProxy("MyHub");
...
// To write received messages:
 myHub.On<string, string>("addMessage", (s1, s2) => {
                        Console.WriteLine(s1 + ": " + s2);
                    });
...
// To send messages:
 myHub.Invoke<string>("Send", name, message).ContinueWith(task1 => {
                            if (task1.IsFaulted)
                            {
                                Console.WriteLine("There was an error calling send: {0}", task1.Exception.GetBaseException());
                            }
                            else
                            {
                                Console.WriteLine(task1.Result);
                            }
                        });

This might work for you too Alexander.

I hope it helps.

Juan

Juan
  • 2,156
  • 18
  • 26
  • Thanks, i was able to send messages a console application but i am also getting exceptions. – Alexander Sep 17 '17 at 09:40
  • I'll try to help using a laptop, this stuff is complicated just with a mobile phone... Lol... But yes, according to the exception message there is something wrong with some parameters, I don't really know if the problem is client side or server side. I'll take a look into it in a couple of hours. Promised. – Juan Sep 18 '17 at 03:41
  • Okay, but the exception is from the client side. – Alexander Sep 18 '17 at 16:29
  • I'd say that David Fowl's answer is right, your exception at client side is because of unmatching arguments, you are sending two and the method expect one, maybe you can create a class to include those properties and only send a serialized object. – Juan Sep 19 '17 at 06:48