Ejemplo de aplicación de consola SignalR

84

¿Existe un pequeño ejemplo de una aplicación de consola o winform que use signalR para enviar un mensaje a un concentrador .net? He probado los ejemplos de .net y he mirado el wiki, pero no me tiene sentido la relación entre el concentrador (.net) y el cliente (aplicación de consola) (no pude encontrar un ejemplo de esto). ¿La aplicación solo necesita la dirección y el nombre del concentrador para conectarse?

¿Si alguien pudiera proporcionar un pequeño fragmento de código que muestre que la aplicación se conecta a un concentrador y envía "Hola mundo" o algo que recibe el concentrador .net?

PD. Tengo un ejemplo de chat de concentrador estándar que funciona bien, si trato de asignarle un nombre de concentrador en Cs, deja de funcionar, es decir, [HubName ("prueba")], ¿sabe el motivo de esto?

Gracias.

Código actual de la aplicación de consola.

static void Main(string[] args)
{
    //Set connection
    var connection = new HubConnection("http://localhost:41627/");
    //Make proxy to hub based on hub name on server
    var myHub = connection.CreateProxy("chat");
    //Start connection
    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();

    //connection.StateChanged += connection_StateChanged;

    myHub.Invoke("Send", "HELLO World ").ContinueWith(task => {
        if(task.IsFaulted)
        {
            Console.WriteLine("There was an error calling send: {0}",task.Exception.GetBaseException());
        }
        else
        {
            Console.WriteLine("Send Complete.");
        }
    });
 }

Servidor Hub. (espacio de trabajo de proyecto diferente)

public class Chat : Hub
{
    public void Send(string message)
    {
        // Call the addMessage method on all clients
        Clients.addMessage(message);
    }
}

Wiki de información para esto es http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-net-client

usuario685590
fuente
OK, en realidad esto funcionó, solo pensé que estaba obteniendo el mismo resultado, solo agregué algunos puntos de parada y Console.ReadLine (); al final. ¡Alarido!.
user685590

Respuestas:

110

En primer lugar, debe instalar SignalR.Host.Self en la aplicación del servidor y SignalR.Client en su aplicación cliente mediante nuget:

PM> Señal de paquete de instalación R. Hosting.Self -Version 0.5.2

PM> Paquete de instalación Microsoft.AspNet.SignalR.Client

Luego agregue el siguiente código a sus proyectos;)

(ejecutar los proyectos como administrador)

Aplicación de consola del servidor:

using System;
using SignalR.Hubs;

namespace SignalR.Hosting.Self.Samples {
    class Program {
        static void Main(string[] args) {
            string url = "http://127.0.0.1:8088/";
            var server = new Server(url);

            // Map the default hub url (/signalr)
            server.MapHubs();

            // Start the server
            server.Start();

            Console.WriteLine("Server running on {0}", url);

            // Keep going until somebody hits 'x'
            while (true) {
                ConsoleKeyInfo ki = Console.ReadKey(true);
                if (ki.Key == ConsoleKey.X) {
                    break;
                }
            }
        }

        [HubName("CustomHub")]
        public class MyHub : Hub {
            public string Send(string message) {
                return message;
            }

            public void DoSomething(string param) {
                Clients.addMessage(param);
            }
        }
    }
}

Aplicación de consola cliente:

using System;
using SignalR.Client.Hubs;

namespace SignalRConsoleApp {
    internal class Program {
        private static void Main(string[] args) {
            //Set connection
            var connection = new HubConnection("http://127.0.0.1:8088/");
            //Make proxy to hub based on hub name on server
            var myHub = connection.CreateHubProxy("CustomHub");
            //Start connection

            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<string>("Send", "HELLO World ").ContinueWith(task => {
                if (task.IsFaulted) {
                    Console.WriteLine("There was an error calling send: {0}",
                                      task.Exception.GetBaseException());
                } else {
                    Console.WriteLine(task.Result);
                }
            });

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

            myHub.Invoke<string>("DoSomething", "I'm doing something!!!").Wait();


            Console.Read();
            connection.Stop();
        }
    }
}
Mehrdad Bahrainy
fuente
Puede utilizar el código anterior en la aplicación de Windows, pero ¿es realmente necesario? No estoy seguro de lo que quiere decir, puede notificar en Windows de otras formas.
Mehrdad Bahrainy
1
el cliente funciona con el servidor 0.5.2 hasta 1.0.0-alpha2, por ejemplo, Install-Package Microsoft.AspNet.SignalR.Client -version 1.0.0- alpha2 nuget.org/packages/Microsoft.AspNet.SignalR.Client/1.0.0-alpha2 (el código y las versiones de SignalR deberían funcionar con .net 4.0 usando VS2010 SP1) he estado tratando de averiguar por qué no podía hacerlo funcionar, finalmente probé el cliente con las primeras versiones de SignalR.
Nick Giles
agradable, realmente útil
Dika Arta Karunia
4
Tenga en cuenta que debe agregar los detectores de eventos (las .On<T>()llamadas al método) antes de llamar al connection.Start()método.
nicolocodev
Merece proporcionar este enlace: docs.microsoft.com/en-us/aspnet/signalr/overview/…
Mohammed Noureldin
24

Ejemplo de SignalR 2.2.1 (mayo de 2017)

Servidor

Paquete de instalación Microsoft.AspNet.SignalR.SelfHost -Version 2.2.1

[assembly: OwinStartup(typeof(Program.Startup))]
namespace ConsoleApplication116_SignalRServer
{
    class Program
    {
        static IDisposable SignalR;

        static void Main(string[] args)
        {
            string url = "http://127.0.0.1:8088";
            SignalR = WebApp.Start(url);

            Console.ReadKey();
        }

        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                app.UseCors(CorsOptions.AllowAll);

                /*  CAMEL CASE & JSON DATE FORMATTING
                 use SignalRContractResolver from
                /programming/30005575/signalr-use-camel-case

                var settings = new JsonSerializerSettings()
                {
                    DateFormatHandling = DateFormatHandling.IsoDateFormat,
                    DateTimeZoneHandling = DateTimeZoneHandling.Utc
                };

                settings.ContractResolver = new SignalRContractResolver();
                var serializer = JsonSerializer.Create(settings);
                  
               GlobalHost.DependencyResolver.Register(typeof(JsonSerializer),  () => serializer);                
            
                 */

                app.MapSignalR();
            }
        }

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

Cliente

(casi lo mismo que la respuesta de Mehrdad Bahrainy)

Paquete de instalación Microsoft.AspNet.SignalR.Client -Version 2.2.1

namespace ConsoleApplication116_SignalRClient
{
    class Program
    {
        private static void Main(string[] args)
        {
            var connection = new HubConnection("http://127.0.0.1:8088/");
            var myHub = connection.CreateHubProxy("MyHub");

            Console.WriteLine("Enter your name");    
            string name = Console.ReadLine();

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

                    myHub.On<string, string>("addMessage", (s1, s2) => {
                        Console.WriteLine(s1 + ": " + s2);
                    });

                    while (true)
                    {
                        Console.WriteLine("Please Enter Message");
                        string message = Console.ReadLine();

                        if (string.IsNullOrEmpty(message))
                        {
                            break;
                        }

                        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);
                            }
                        });
                    }
                }

            }).Wait();

            Console.Read();
            connection.Stop();
        }
    }
}
ADOConexión
fuente
4
No funciona para mí ... lanza una excepción de referencia nula en WebApp.Start ()
Fᴀʀʜᴀɴ Aɴᴀᴍ
Tal vez por casualidad, ¿ahora sabe cómo establecer la configuración de serialización json (por ejemplo, camelCase) globalmente en este servidor de señalización auto alojado?
Xaris Fytrakis
2
@XarisFytrak es muy fácil, Ive actualiza el anwser, necesita un solucionador de contratos desde aquí: stackoverflow.com/questions/30005575/signalr-use-camel-case así como DateFormatHandling = DateFormatHandling.IsoDateFormat, si lo consume desde js.
ADOConnection
@ADOConnection Gracias por la rápida respuesta. El problema ahora es cuando se llama al método desde un cliente .net. Por ejemplo, si estoy en la clase Hub, llamo a esto: HubContext.Clients.All.UpdateMetric (new {Data = "xxx", Something = "yyy"}, username); Recibo la respuesta json con la configuración de serialización correcta (Camel Cased). Pero si lo llamo con datos pasados ​​de un cliente (cliente asp.net) como este: public void UpdateMetric (métricas de objeto, cadena de nombre de usuario) {HubContext.Clients.All.UpdateMetric (métricas, nombre de usuario); el resultado en el cliente no es Camel Cased.
Xaris Fytrakis
2

Esto es para dot net core 2.1; después de muchas pruebas y errores, finalmente logré que esto funcionara perfectamente:

var url = "Hub URL goes here";

var connection = new HubConnectionBuilder()
    .WithUrl($"{url}")
    .WithAutomaticReconnect() //I don't think this is totally required, but can't hurt either
    .Build();

//Start the connection
var t = connection.StartAsync();

//Wait for the connection to complete
t.Wait();

//Make your call - but in this case don't wait for a response 
//if your goal is to set it and forget it
await connection.InvokeAsync("SendMessage", "User-Server", "Message from the server");

Este código es de su típico cliente de chat de SignalR pobre. El problema con el que yo y lo que parece ser que muchas otras personas nos hemos encontrado es establecer una conexión antes de intentar enviar un mensaje al hub. Esto es fundamental, por lo que es importante esperar a que se complete la tarea asincrónica, lo que significa que la estamos sincronizando esperando a que se complete la tarea.

dislexicanaboko
fuente
en realidad, podría encadenar el inicio y esperar como conexión.StartAsync.Wait ()
DiTap