Monday, 25 May 2015

Continuing with SignalR



Hola amigo!!!

Ella unnav? (How are you? in Telugu :D )

Anyways, so here we continue with the second part of making apps with SignalR, a pretty cool library, for first part refer:







So struggling to figure out how to implement signalR in console apps that with .NET Client, I finally got the way through it.

You need to have two separate projects(preferably):
1. Server 
2. Client

Inside Server:

I have a main class, a startup class and a hub.
Before starting make sure you have added relevant references beforehand.
How?
Right click the project name and select Manage NuGet Packages, install:
signalR .NET client : Microsoft ASP.NET SignalR .NET Client
and  also SelfHosting 

One thing that comes into scens and is the most important is Cross Domain Communication.

Both the server and the client are separate projects now, so the client must be able to identify and connect to the server running in parallel as a separate project. What changes do we need to incorporate with the same?

Here they are:

Majorly the Startup.cs OWIN class gets changed to support cross domain connection.
Refer this for more details on what it is:

http://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#crossdomain

So the startup file is changed to:

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Cors;
using Microsoft.AspNet.SignalR;
 
[assemblyOwinStartup(typeof(BroadcasterConsole.Startup))]
 
namespace BroadcasterConsole
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Map("/signalr", map =>
            {
                map.UseCors(CorsOptions.AllowAll);
                var hubConfiguration = new HubConfiguration
                {
                    EnableJSONP = true
                    
                };
                map.RunSignalR(hubConfiguration);
            });
            
        }
    }
}


CorsOptions.AllowAll  will help your cross domain client to connect to te serevr. Also, please don't miss out the line:  [assemblyOwinStartup(typeof(BroadcasterConsole.Startup))]

Theses changes will make your server been detected and connected by the cross domain clients.

Rest of the server code is more or lesss the same as teh previous code. We need to have a hub class and a main class, I preferred to have them both in same namespace and it goes like this:

namespace BroadcasterConsole
{
    class Broadcast
    {
        static void Main(string[] args)
        {
            string url = "http://localhost:8088";
            try
            {
                using (WebApp.Start(url))
                {
                  //Have your code here
                }
 
        }
    }
 
 
 
 
    [HubName("broadcaster")]  
 
//Don't forget this line above, this name helps you to connect to the hub from the client side
    public class Broadcaster : Hub
    {
 
        public override Task OnConnected()
        {
            Console.WriteLine("Hub OnConnected {0}\n", Context.ConnectionId);
 
            return (base.OnConnected());
        }
 //Define your own hub methods
 
        public override Task OnReconnected()
        {
            Console.WriteLine("Hub OnReconnected {0}\n", Context.ConnectionId);
            return (base.OnDisconnected(true));
        }
    }
}


So, let's come back to the client side. I tried to have clients in different languages.

A peek into Javascript Client:

Firstly, include these scripts in this particular order:

   <!--Reference the jQuery library. -->
   <script src="Scripts/jquery-2.1.4.js"></script>
   <!--Reference the SignalR library. -->
   <script src="Scripts/jquery.signalR-2.2.0.js"></script>
 
 
   <!--Reference the autogenerated SignalR hub script. -->
 
   <script src="http://localhost:8088/signalr/hubs" type="text/javascript"></script>


Please see I have hosted my server on 8088 port, change it accordingly, as per the url of your hosted server.

Here goes your main connection code:

<script type="text/javascript">
       
       $.connection.hub.url = 'http://localhost:8088/signalr';
       var hubProxy = $.connection.broadcaster;
       hubProxy.client.addMessage = function (message) {
     
           //message is a c# struct Request object.
    
           // Add the message to the page.
           $('#discussion').append('<li><strong> ' + document.getElementById('displayname').value + ' received request  Name:' + message.Name +  '\n   Program:' + message.Program +  '\n     Input:' + message.Input
               + '</strong>:&nbsp;&nbsp;</li>');
       };
 
       $.connection.hub.start().done(function(){
       
           alert('Now connected, connection ID=' + $.connection.hub.id);
           $('#displayname').val(prompt('Which process are you?'''));
           hubProxy.server.registerMe(document.getElementById('displayname').value);
           $('#sendoutput').click(function () {
 
               hubProxy.server.getClientOutput({ "Name""JS Client""Result": $('#output').val() });
 
               $('#output').val('').focus();
           });
       });
     
      
   </script>


Its fine if you don't get any of the above code since it would be a bit out of the context you are into. just focus on highlighted lines.

Set the hub url, create a hub Proxy.
Prior to starting teh connection, add the client side methods that the hub can call, for example here we have: addMessage.
Then start the connection by this line:  $.connection.hub.start().done.

You can call server side methods by : hubProxy.server.getClientOutput (//required params)


There we finish with the JavaScript client, we can do the same with clients for different languages:

.NET Client:

//Set connection
           var connection = new HubConnection("http://localhost:8088/");
//Make proxy to hub based on hub name on server
           myHub = connection.CreateHubProxy("Broadcaster");
           
//Add client side methods

           myHub.On<Request>("addMessage", param =>{
              //Define your method
           });
 
//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();
 //Invoking hub methods

           myHub.Invoke<string>(<Method Name as is>, clientName)


C++ Client:
Here is a detailed guide to do the same with C++. 
https://github.com/aspnet/SignalR-Client-Cpp

It is pretty simple to use, in case you have any queries, leave in comments below. So that was all folks, see you in next post! Till then, Happy Hacking! Meanwhile, get your signals across using SignalR :D



Tuesday, 19 May 2015

My Experiments with Truth, oops sorry, SignalR

So what have I been upto these days is a really cool library SignalR

Wanna know more about its where and how abouts? Visit this:


 


 So , after a little researching I got to know you can create two sorts of clients here: JavaScript and .NET clients.

If your mind is like: What Clients?
Dude, you have not gone through the video, eh? :P

Anyways, so Signal R actually facilitates real time conversation, the ones you see in chats like IRC (Internet Relay Chat) . So a message can be broadcasted simultaneously to multiple clients and you can make it possible to gather the responses from the client too.

I have not yet covered the thread safety and async-ness into consideration but overall my code goes somewhat like this:
You can create a broadcast server, that is essentially the hub.

The major files I have are these:
1. Hub Class: Right click your project and select add item>SignalR Hub Class v2

Make sure you are creating a web application in visual studio, prior to doing this otherwise this option may not come.
Also, this way it helps adding all relevant SignalR references to your project.
The hub class has simple code as:

public class BroadcastHub : Hub
  {
      
      public void Send(string input)
      {
          Clients.All.broadcastMessage(input);
      }
 
      public void Receive(string name, string output)
      {
          System.Diagnostics.Debug.WriteLine(name + " has given output:" + output);
      }
 
  }


2. Owin Startup Class: Right click the project name and select add item> OWIN startup class.

While I am still in a process to learn more about OWIN, the most I can tell you is :
"OWIN is a specification that defines an API for framework and servers to cooperation. The point of OWIN is to decouple server and application. For example, ASP.NET Identity uses OWIN security, SignalR self hosting uses OWIN hosting, and etc., the examples all use OWIN, therefore they all need to have a startup class, that is defined in "Startup.cs" file."

So inside your startup.cs owin class you would be having code like:
 
using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
 
[assemblyOwinStartup(typeof(ServerBroadcast.Startup))] namespace ServerBroadcast
{     
public class Startup     
{         
public void Configuration(IAppBuilder app)         
{             
app.MapSignalR();         
}     
}
}

3. Client : I have javascript client so it was basically an html page. I named it FakeClient.
Major methods it uses:
<script type="text/javascript">
        $(function () {
            // Declare a proxy to reference the hub.
            var chat = $.connection.broadcastHub;
            // Create a function that the hub can call to broadcast messages.
            chat.client.broadcastMessage = function (message) {
                // Html encode display name and message.
                var encodedMsg = $('<div />').text(message).html();
                // Add the message to the page.
                $('#discussion').append('<li><strong> ' + document.getElementById('displayname').value + ' received '
                    + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
            };
            // Get the user name and store it to prepend to messages.
            $('#displayname').val(prompt('Which process are you?'''));
            // Set initial focus to message input box.
            $('#message').focus();
            // Start the connection.
            $.connection.hub.start().done(function () {
                    $('#sendoutput').click(function () {
                  
                    chat.server.receive(document.getElementById('displayname').value, $('#output').val());
                    
                    $('#output').val('').focus();
                });
            });
        });
    </script>

From the code, it is evident that once we get connection from the hub in var chat, we can access the server and client part of it as, chat.server.receive, note that receive method is defined in my hub and chat.client.broadcastMessage , broadcastMessage has been a defined method for signalR client.
 
 
 


4. Broadcaster: Since I wanted to give a face to my hub too so I created one more html page and set hat as the start page.

It has simple code as:

<script type="text/javascript">
       $(function () {
           // Declare a proxy to reference the hub.
           var chat = $.connection.broadcastHub;
                   
           // Set initial focus to message input box.
           $('#message').focus();
           // Start the connection.
           $.connection.hub.start().done(function () {
               $('#sendmessage').click(function () {
 
                   // Call the Send method on the hub.
                   chat.server.send($('#message').val());
 
                   // Clear text box and reset focus for next comment.
                   $('#message').val('').focus();
               });
               $('#addclient').click(function () {
                   window.open('http://localhost:44621/FakeClient.html''_blank');
                   window.focus();
 
 
               });
           });
       });
   </script>
 
 
 
So that's pretty much it and you are done, with signalR implementation.
 
Next we would be covering on how to do the same with .NET clients...
Till then see you!
 
Happy hacking!
 


 

A secret love message ~

Hmm, so the trick of putting up a catchy seasonal title worked out, we got you here! Folks, we will be talking about a really cool tech...