Esempio di app SignalR Console


85

Esiste un piccolo esempio di un'app per console o winform che utilizza signalR per inviare un messaggio a un hub .net ?. Ho provato gli esempi .net e ho guardato il wiki, ma non ha senso per me la relazione tra l'hub (.net) e il client (app console) (non sono riuscito a trovare un esempio di questo). L'app necessita solo dell'indirizzo e del nome dell'hub per connettersi ?.

Se qualcuno potesse fornire un piccolo bocconcino di codice che mostra l'app che si connette a un hub e invia "Hello World" o qualcosa che riceve l'hub .net ?.

PS. Ho un esempio di chat hub standard che funziona bene, se provo ad assegnargli un nome hub in Cs, smette di funzionare cioè [HubName ("test")], conosci il motivo?

Grazie.

Codice dell'app console corrente.

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

Hub Server. (area di lavoro del progetto diversa)

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

Info Wiki per questo è http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-net-client


OK in realtà questo ha funzionato solo pensato che stavo ottenendo lo stesso risultato solo aggiunto alcuni punti di arresto e Console.ReadLine (); alla fine. Whoop !.
user685590

Risposte:


111

Prima di tutto, dovresti installare SignalR.Host.Self sull'applicazione server e SignalR.Client sull'applicazione client da nuget:

PM> Install-Package SignalR.Hosting.Self -Version 0.5.2

PM> Pacchetto di installazione Microsoft.AspNet.SignalR.Client

Quindi aggiungi il seguente codice ai tuoi progetti;)

(esegui i progetti come amministratore)

App della console del server:

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

App console client:

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

Puoi usare il codice sopra nell'applicazione Windows ma è davvero necessario ?! Non sono sicuro di cosa intendi, puoi notificare in Windows in altri modi.
Mehrdad Bahrainy

1
client funziona con il server 0.5.2 fino a 1.0.0-alpha2, ad esempio Install-Package Microsoft.AspNet.SignalR.Client -version 1.0.0- alpha2 nuget.org/packages/Microsoft.AspNet.SignalR.Client/1.0.0-alpha2 (il codice e le versioni di SignalR dovrebbero funzionare con .net 4.0 utilizzando VS2010 SP1) ho cercato di capire perché non riuscivo a farlo funzionare, alla fine ho provato il client con le prime versioni di SignalR.
Nick Giles

bello, davvero utile
Dika Arta Karunia

5
Nota che devi aggiungere i listener di eventi (le .On<T>()chiamate al metodo) prima di chiamare il connection.Start()metodo.
nicolocodev


24

Esempio per SignalR 2.2.1 (maggio 2017)

server

Pacchetto di installazione 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

(quasi la stessa risposta di Mehrdad Bahrainy)

Pacchetto di installazione 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();
        }
    }
}

4
Non funziona per me ... genera un'eccezione con riferimento nullo su WebApp.Start ()
Fᴀʀʜᴀɴ Aɴᴀᴍ

Forse per caso, ora come impostare le impostazioni di serializzazione json (ad esempio camelCase) a livello globale in questo server signalr self-hosted?
Xaris Fytrakis

2
@XarisFytrakis super facile, Ive aggiorna il anwser, hai bisogno di un risolutore di contratti da qui: stackoverflow.com/questions/30005575/signalr-use-camel-case così come DateFormatHandling = DateFormatHandling.IsoDateFormat, se lo consumi da js.
Collegamento ADOC

@ADOConnection Grazie per la rapida risposta. Il problema ora è quando si chiama il metodo da un client .net. Ad esempio, se sono nella classe Hub, chiama questo: HubContext.Clients.All.UpdateMetric (new {Data = "xxx", Something = "yyy"}, username); Ottengo la risposta json con le impostazioni di serializzazione corrette (Camel Cased). Ma se lo chiamo con dati passati da un client (client asp.net) come questo: public void UpdateMetric (metriche oggetto, stringa nome utente) {HubContext.Clients.All.UpdateMetric (metriche, nome utente); il risultato sul client non è Camel Cased.
Xaris Fytrakis


3

Questo è per dot net core 2.1 - dopo molti tentativi ed errori ho finalmente ottenuto che funzioni perfettamente:

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

Questo codice proviene dal tipico client di chat di SignalR povero. Il problema che io e quello che sembra che molte altre persone abbiamo incontrato è stabilire una connessione prima di tentare di inviare un messaggio all'hub. Questo è fondamentale, quindi è importante attendere il completamento dell'attività asincrona, il che significa che la stiamo rendendo sincrona aspettando il completamento dell'attività.


potresti effettivamente concatenare l'inizio e attendere come connessione.StartAsync.Wait ()
DiTap

1

Per costruire sulla risposta di @ dyslexicanaboko per dotnet core, ecco un'applicazione per console client:

Crea una classe helper:

using System;
using Microsoft.AspNetCore.SignalR.Client;

namespace com.stackoverflow.SignalRClientConsoleApp
{
    public class SignalRConnection
    {
        public async void Start()
        {
            var url = "http://signalr-server-url/hubname";

            var connection = new HubConnectionBuilder()
                .WithUrl(url)
                .WithAutomaticReconnect()
                .Build();

            // receive a message from the hub
            connection.On<string, string>("ReceiveMessage", (user, message) => OnReceiveMessage(user, message));

            var t = connection.StartAsync();

            t.Wait();

            // send a message to the hub
            await connection.InvokeAsync("SendMessage", "ConsoleApp", "Message from the console app");
        }

        private void OnReceiveMessage(string user, string message)
        {
            Console.WriteLine($"{user}: {message}");
        }

    }
}

Quindi implementa nel punto di ingresso dell'app della console:

using System;

namespace com.stackoverflow.SignalRClientConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var signalRConnection = new SignalRConnection();
            signalRConnection.Start();

            Console.Read();
        }
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.