Showing posts with label SignalR. Show all posts
Showing posts with label SignalR. Show all posts

Thursday, August 21, 2014

Self hosting of SignalR using Owin

We know that SignalR is the Microsoft’s push solution in web application. Prior to Owin the concept was like that. Introduction of Owin has changed the scenario. Now SignalR can able to host with some other stand alone application.  It’s not needed to configure SignalR hub within IIS server.  We know that OWIN(Open Web Interface for .NET) which has introduced by Microsoft is a specification which sits between Web server and Web application.

The reason to introduce Owin is to reduce the dependency of Web application on Web Server.  For example, if we implement some Owin specification (most popular is KATANA) in our application then may be our application can able to run in any server irrespective of IIS.


The Owin has given facility of self hosting which we can adapt to host out SignalR hub application in single stand alone process. The process may be one exe or Windows service or something else.

Why self hosting?
If you have concept of SignalR 1.0 and implemented in your web application then you may ask the question. We have hosted SignalR in IIS server along with web application, that’s easy and fine. Here are few advantage of self hosting.

  •          If there is no environment to host application in IIs
  •          If we don’t want to pressure on IIS

So, those might be valid reason where self hosting may come in picture. So, let’s implement example of self hosting and access SignalR hub from other application.

Let’s take one console application and install below packages from nugget package manager. The below package is to install SignalR in self hosting environment.

Install-Package Microsoft.AspNet.SignalR.SelfHost

Now, as the hosting environment will be stand alone application and client will be calling the application from some other domain, we have to enable Cross Origin Resource Shairing(CORS) in application. Here is the package for it.

Install-Package Microsoft.Owin.Cors

Once you install both the packages, you should see those references in application. 




Fine, we have setup the necessary references, now we will define Owin startup class.  This startup class will be the entry point of application and we are enabling CORS in this entry point. Here is sample code of the startup class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Owin;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Hosting;
using Microsoft.Owin;

[assembly: OwinStartup(typeof(OWINApplication.Startup))]

namespace OWINApplication
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(CorsOptions.AllowAll);
            app.MapSignalR();
        }
    }
}

The AllowAll property indicates that we want to allow all domains to request to the SignalR hub.  This is both pros and cons. If we allow all domains then many applications from different domain can able to consume the SignalR hub, this is the advantage and at the same time we have to implement strong access policy and security for various domains.

Now, we will implement SignalR hub where we will define the hub class and the function which will broadcast the message across client. Here is simple implementation.

public class messageHub : Hub
    {
        public void sayHello()
        {
            Clients.All.sendMessage("Welcome to shelf hosting..");
        }
    }

It’s too simple, the sayHello() function will invoke sendMessage() function which is defined in client end of SignalR subscriber.

Now , we have to host the application in some endpoint .  Within Main() function we have defined the url and arbitrary port where SignalR hub will host.

public class Program
    {
        public static void Main(string[] args)
        {
            string url = "http://localhost:1234";
            using (WebApp.Start(url))
            {
                Console.WriteLine("Server running...");
                Console.ReadLine();
            }

            Console.ReadLine();
        }
    }

Once we run the application, we will see below screen. 

We have hosted SignalR server successfully .now we will consume the service from client application. It’s not mandatory that the client should be JavaScript client always, but it’s normal scenario where we consume SignalR server from JavaScript client.

Here we have implemented one simple client which will consume SignalR hub. Have a look on below code.

    <script src="~/Scripts/jquery-1.6.4.min.js"></script>
    <script src="~/Scripts/jquery.signalR-2.1.1.min.js"></script>
    <script src="http://localhost:1234/signalr/hubs"></script>
   
    <script>
        $(function () {

            $.connection.hub.url = "http://localhost:1234/signalr";
            var appProxy = $.connection.messageHub;

            appProxy.client.sendMessage = function (message) {
                alert(message);
            }

            $.connection.hub.start().done(function () {
                appProxy.server.sayHello();
            });

        });
    </script>

And once we run the application, we will see below output. The message has come from hub function which we have hosted in console application.

Conclusion:-
In this example we have learned to host SignalR server in self hosting application.  Hope it has given you a clear idea about self hosting of SignalR application.

Saturday, August 16, 2014

Initialize SignalR hub within controller of AngularJS

In this example we will see how SignalR and AngularJS fits side by side in single application. We know that SignalR is the microsoft’s solution to push data from server and AngularJS is google’s solution to implement MVC architecture in client code.


From my personal experience I can say that, both the technologies are just awesome and they work cool together.

So, let’s start with code implementation. Take one MVC or Web Form application and give reference of SignalR hub. The latest version of SignalR at the time of writing this article is 2.0
Once the hub created, just create one hub class (I have created chatHub) and derive it from Hub.  In The hub class is located in below namespace.

using Microsoft.AspNet.SignalR.Hubs;

Again,the Hub class is derived from BaseHub class. which is the parent class of all. Here is our simple hub implementation.


    [HubName("chatHub")]
    public class chatHub : Hub
    {

        public void broadcastHello()
        {
            Clients.All.receiveHello("Welcome to Hub");
        }
    }

Fine, now we will implement controller in AngularJS where we are going to consume hub function. So proxy will create within controller.
Let’s define one module which we will use in application. Here is “myApp” module

var app = angular.module('myApp', []);

Let’s attach one controller to the module. Here we have implemented “dataService” controller. Have a look on below code.


app.controller('dataService', function ($scope) {

    var proxy = $.connection.chatHub;

    $.connection.hub.start().done(function () {
        console.log('Hub Connected');
    });

    //listener to hub
    proxy.client.receiveHello = function (message) {
        alert(message);
    }

    //call hub method from here.
    $scope.getMessage = function () {
        proxy.server.broadcastHello();
    };

});


Just have a look that, we have created proxy to chatHub on fly and assigned to proxy object. There are two methods which is defined associated with scope of angular controller.

The receiveHello function will listen to hub and hub can able to invoke it from server side and the getMessage will ca;; broadcastHello() function which we have defined to hub class.

Now, we will implement the client page from where we will invoke controller function.


@{
    Layout = null;
}
<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Data</title>
    <script src="~/Scripts/angular.min.js"></script>
    <script src="~/Scripts/jquery-1.6.4.min.js"></script>
    <script src="~/Scripts/jquery.signalR-2.1.1.min.js"></script>
    <script src="~/signalr/hubs"></script>
    <script src="~/Scripts/SignalRHub.js"></script>

</head>
<body>
    <div>
    <body ng-controller="dataService">

        <input type="button" name="gatdata" value="Get Data" ng-click="getMessage()" />
    </body>
    </div>
</body>
</html>

Once we click on the button, it will invoke getMessage function and will call to boradcastHello()  function. You should see the below output, if everything goes well.



A smart way to fit SignalR with AngularJS

We know that SignalR is Microsoft’s solution to solve data pushing from server which has introduced in the year of 2011. Sine this year Microsoft has release couple of version of SignalR and the latest version at this time of writing article is 2.0

At the same time Angular is another framework which has bring another revolution in client side development. Now there is no way to mess all code in client even the project is large in size. Angular will help to implement MVC structure in client.

Fine, I hope you all you have more or less knowledge of both and you want to see how they fit together side by side?  

Ok, then you are in right place. We will implement SinglaR hub and then we will implement client hub factory using AngularJS and then we will consume server hub from controller. So, in nutshell, we will take help of AngularJS to create SignalR proxy and to call hub method using the proxy.
So, let’s create one MVC /normal Web Form application and give install SignalR from HuGet package manager.


Here is our simple hub code where the hub name is chatHub, you are free to give anything.

    [HubName("chatHub")]
    public class chatHub : Hub
    {
        public void broadcastHello()
        {
            Clients.All.receiveHello("Welcome to Hub");
        }
    }

Now, we will create SingnalR factory using angularJS where we will manage hub connection and proxy creation.  Have a look on below code. The module name is “myApp”, you are free to give anything.


var app = angular.module('myApp', []);

app.factory("signalrFactory", function ($rootScope, $http, $timeout) {
    var factory = {};
    factory.connection = $.connection;

    var startDoneFunctions = [];
    var debounce;

    factory.start = function (done) {
        factory.connection.hub.stop();

        if (done) {
            if (startDoneFunctions.indexOf(done) == -1) {
                startDoneFunctions.push(done);
            }
        }
        if (debounce) $timeout.cancel(debounce);
        debounce = $timeout(function () {
            factory.connection.hub.start().done(function () {
                for (var x = 0; x < startDoneFunctions.length; x++) {
                    startDoneFunctions[x]();
                }
            });
        }, 100);
    };

    return factory;
});

Now we will create our controller which will talk with the signalRFactory. Here is the code of controller.

app.controller('dataService', function ($scope, signalrFactory) {

    $scope.customerHub = signalrFactory.connection.chatHub;

    //client function to listen hub
    $scope.customerHub.client.receiveHello = function (customer) {
        $scope.returnData=  customer;
    };

    $scope.getMessage = function () {
        signalrFactory.start(function () {
            $scope.customerHub.server.broadcastHello();

        });
    };
});


The controller is pretty easy to understand, in first line we are creating hub proxy on fly by communicating with signalrFactory. Have a look that, we have injected signalrFactory to controller. receiveHello() is the client function which will listen to hub and getMessage() is the function which will call to broadcastHello() function which is defined in hub class.

Now, we will create html client from where we will consume controller of AngularJS . Have a look on below code.

@{
    Layout = null;
}
<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Data</title>
    <script src="~/Scripts/angular.min.js"></script>
    <script src="~/Scripts/jquery-1.6.4.min.js"></script>
    <script src="~/Scripts/jquery.signalR-2.1.1.min.js"></script>
    <script src="~/signalr/hubs"></script>
    <script src="~/Scripts/SignalRHub.js"></script>

</head>
<body>
    <div>
    <body ng-controller="dataService">
       
        <div ng-data="returnData"></div>
        <input type="button" name="gatdata" value="Get Data" ng-click="getMessage()" />
    </body>
    </div>
</body>
</html>

And when we will press the button, we should see the below screen.