Alternative Implementation Techniques of SignalR

Keywords: C# Javascript JQuery

A long time ago, I published an article entitled< Three ways to learn SignalR through three DEMO s > In that article, the commonly used signal R implementation method in WEB application is introduced in detail. Today, we use signal R to achieve other uses, such as: B/S and C/S communication, such as: C/S and C/S communication.

First, B/S and C/S communicate with each other (ASP.NET broadcasts messages to Winform). First, the effect is as follows:

As shown in the figure above, the server is used to send the message (referring to sending in C # code), and then winform receives the message.

As shown in the figure above, the client (browser) JS proxy object is taken to send the message, and then winform receives the message.

The implementation code of the above example is as follows:

ASP.NET Server Code:

MyHub:

    [HubName("myHub")]
    public class MyHub : Hub
    {
        public static Action<string> SendMsgAction = null;
        public MyHub()
        {
            SendMsgAction = new Action<string>(SendMsg);
        }

        private void SendMsg(string msg)
        {
            Clients.All.RecvMsg(msg);
        }

        [HubMethodName("broadcast")]
        public void Broadcast(string msg)
        {
            if ("broadcast".Equals(Context.QueryString["identity"])) //Only broadcasters can broadcast messages.
            {
                SendMsg(msg);
            }
        }


        public override System.Threading.Tasks.Task OnConnected()
        {
            return base.OnConnected();
        }

        [HubMethodName("testConnect")]
        public void TestConnect()
        {
            System.Diagnostics.Debug.Write("ddd");
        }
    }

ASP.NET Page: (Server control is used for demonstration to send to server)

        <div>
            //Broadcast message: <input type="text" id="txtmsg" runat="server"/>
            <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Server Send" />
        </div>

ASP.NET CS code:

        protected void Button1_Click(object sender, EventArgs e)
        {
            if(MyHub.SendMsgAction!=null)
            {
                MyHub.SendMsgAction("Server sends message-" + txtmsg.Value);
            }
        }

In particular, because MyHub generates instances only when it is connected, we can't get MyHub instances directly from the server, so when we use the MyHub constructor, we expose SendMsg to the static endMsgAction delegation, so that the server can directly determine whether SendMsgAction is subscribed or not to send messages. This is a clever way, of course, if you have a better way, welcome to exchange.

The method of sending through browser is the same as that described in previous articles. Here we use proxy mode. The ASP.NET page code is as follows: (not too much introduction)

    <script src="<%=ResolveUrl("~/Scripts/jquery-1.10.2.min.js") %>" type="text/javascript"></script>
    <script src="<%=ResolveUrl("~/Scripts/jquery.signalR-2.2.2.min.js") %>" type="text/javascript"></script>
    <script src="<%=ResolveUrl("~/signalr/hubs") %>" type="text/javascript"></script>


        <div>
            //Broadcast message: <input type="text" id="txtmsg2"/>
            <input type="button" id="btnSend" value="Client Send" />
        </div>


    <script type="text/javascript">
        $(function () {
           
            var myhub = $.connection.myHub;
            $.connection.hub.qs = { "identity": "broadcast" };
            $.connection.hub.start().done(function () {
                $("#btnSend").click(function () {
                    var msg = $("#txtmsg2").val();
                    myhub.server.broadcast("Client sends message-" + msg)
                    .done(function () {
                        alert("Send successfully!");
                    }).fail(function (e) {
                                alert(e);
                                $("#txtmsg2").focus();
                   });
                });
            });

        });
    </script>

Here's a note: when we define MyHub class, according to CSharp's code specification, class name and method name are capitalized, but the proxy JS class and method name generated automatically by JS will become JS's life specification, that is, the first letter of function name is lowercase, such as MyHub - > myHub, so in order to be compatible with JS calls, HubName and HubMethodNa are used to define Hub class. Me feature, specifying a unified name.

winform client receives message steps:

1. Install SignalR.Client related components through NuGet

2.Winform CS code:

    public partial class Form1 : Form
    {
        private HubConnection connection = null;
        private IHubProxy hubProxy = null;
        private System.Threading.SynchronizationContext syncContext = null;

        public Form1()
        {
            InitializeComponent();
            syncContext = System.Threading.SynchronizationContext.Current;
        }

        private  void Form1_Load(object sender, EventArgs e)
        {
           CreateHubConnection();
        }

        /// <summary>
        /// Create Hub proxy class and start
        /// </summary>
        private void CreateHubConnection()
        {
            connection = new HubConnection("http://Localhost: 3510/signalr"; //SignalR server address
           hubProxy = connection.CreateHubProxy("MyHub");
           hubProxy.On<string>("RecvMsg", RecvMsg); //Subscribe to receive messages
           connection.Start().Wait();
        }
        
        /// <summary>
        /// Receiving Messages from SignalR Server
        /// </summary>
        /// <param name="msg"></param>
        private void RecvMsg(string msg)
        {
            syncContext.Post((o) => {
                textBox1.Text += string.Format("{0:yyyy-MM-dd HH:mm:ss}{1}\r\n", DateTime.Now, o);
            }, msg);
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            connection.Dispose();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            hubProxy.Invoke("TestConnect");//Method of calling SignalR server
        }

    }

From the above code, it can be seen that the principle of JS proxy class generated by ASP.NET page is basically the same. They interact with the server through proxy class and communicate through HTTP protocol.

2. C/S and C/S communicate with each other (winform and winform). In fact, the server is B/S in essence, but we adopt SignalR self-Host (OWIN self-Host is used in it), that is to say, we boarded the website to winform, but we only use WinForm to operate it better. The effect is as follows:

winform server implementation process:

1. Install Microsoft.AspNet.SignalR and Microsoft.AspNet.SignalR Self Host respectively through NuGet, as shown below:

 

2. Add the Startup class file and add the mapping SignalR in it. The code is as follows: (same as the Startup code of ASP.NET server)

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }

3. Write the boarding code of OWIN, MyHub is the same as above, so it will not be posted.

    public partial class Form1 : Form
    {
        private IDisposable webHost = null;

        public static Form1 Current = null;

        public Form1()
        {
            InitializeComponent();
            this.Text = "SignalR Winform Server side";
            Current = this;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                webHost = WebApp.Start<Startup>("http://localhost:3512");
                label2.Text = "http://localhost:3512";
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
                webHost.Dispose();
            }
            catch
            { }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if(MyHub.SendMsgAction!=null)
            {
                MyHub.SendMsgAction(textBox1.Text);
            }
        }

        public void ShowMsg(string msg)
        {
            this.Invoke(new MethodInvoker(() => {
                listBox1.Items.Add(msg);
            }));
        }
    }

Here are a few details to be noted:

1. After installing Microsoft.AspNet.SignalR, the Sciprts folder will be generated in the project, which can be deleted in the winform project.

2. After installing Microsoft.AspNet.SignalR Self Host, compilation may be okay, but when running, you may report that you find a matching OWin assembly. This is because of the OWIN version problem, you just need to install the specified OWIN version separately.

Posted by mickeyunderscore on Sun, 02 Jun 2019 16:43:06 -0700