Saturday, December 1, 2012

SignalR in Web, WPF, Console and Windows Services App in VB


Update: I have updated this post to reflect the latest SignalR (1.0.1) release.  This is some testing I did with SignalR in VB for different kinds of .Net projects like Windows Service, console and WPF application.  This post has different sections and each section has its own .Net solution so you can run them individually.  All the sourcecode for this blog post is available on my github page.  There are two SignalR Owin Host applications, a Console application and a Windows Services Application written in Vb.NET and it will be consumed by various .NET client applications such as Console Application, Web Application using Javascript, WPF Application using VB.Net.

SignalR Owin Hosts
    Console Application
    Windows Services Application
SignalR Owin Clients
    Console Application
       Web Application
       WPF Application

So let’s get started by first creating our SignalR Owin Host Console Application. 

SignalR Server Console Application in VB
Create a console application in VB and Install following nuget packages using Package Manager Console to create SignalR Hub.

>Install-Package Microsoft.Aspnet. Owin.Hosting -pre
>Install-Package Microsoft.Aspnet. Owin.Host.HttpListener -pre
>Install-Package Microsoft.Aspnet.Signalr.Owin

Without further due here is the code to start the server and create a hub which will start sending messages to clients upon arrival.
---------------------------------------
Imports Microsoft.AspNet.SignalR
Imports Microsoft.AspNet.SignalR.Hubs
Imports Microsoft.Owin.Hosting
Imports Owin
Module Module1
    Sub Main()
        Dim url As String = "http://localhost:8080/"
        Using WebApplication.Start(Of Startup)(url)
            Console.ForegroundColor = ConsoleColor.Green
            Console.WriteLine("Server running on {0}", url)
            Console.WriteLine("Press any key to start sending events to connected clients")
            Console.ReadLine()
            Dim context As IHubContext = GlobalHost.ConnectionManager.GetHubContext(Of MyHub)()
            For x As Integer = 0 To 100
                System.Threading.Thread.Sleep(3000)
                Console.WriteLine("Server Sending Value to Client X: " + x.ToString())
                context.Clients.All.addMessage(x.ToString())
            Next
            Console.ReadLine()
        End Using
    End Sub
    Public Class Startup
        Public Sub Configuration(ByVal app As IAppBuilder)
            Dim config = New HubConfiguration With {.EnableCrossDomain = True}
            app.MapHubs(config)
        End Sub
    End Class
    <HubName("myHub")> _
    Public Class MyHub
        Inherits Hub
        Public Sub Chatter(param As String)
            Console.WriteLine(param)
            Clients.All.addMessage(param)
        End Sub
    End Class
End Module
-----------------------------------------------
 IHubContext will give you access to all the clients and then you can communicate to all the clients. When you run this application you will see the following screenshot.  Once you have your client code written then you can press any key and it will start sending values to connected clients. 


Now lets consume this Self Host in a Client Console Application
SignalR Client Console Application in VB.  
Create a Console Application in VB and install nuget package using Package Manager Console. 

>Install-Package Microsoft.Aspnet.Signalr.Client

Then paste the following code into your Module1.vb page.  And run the application assuming you have already started the host application.

--------------------------------------
Imports Microsoft.AspNet.SignalR.Client.Hubs
Imports Microsoft.AspNet.SignalR
Module Module1

    Sub Main()
        Dim connection = New HubConnection("http://localhost:8080")

        Dim myHub = connection.CreateHubProxy("myHub")

        connection.Start().Wait()
        Console.ForegroundColor = ConsoleColor.Yellow
        myHub.Invoke(Of String)("chatter""Hi!! Server") _
        .ContinueWith(
            Sub(task)
                If task.IsFaulted Then
                    Console.WriteLine("Could not Invoke the server method Chatter: {0}", _
                                      task.Exception.GetBaseException())
                Else
                    Console.WriteLine("Success calling chatter method")
                End If
            End Sub)

        myHub.On(Of String)("addMessage", _
            Sub(param)
                Console.WriteLine("Client receiving value from server: {0}", param.ToString())
            End Sub)
        Console.ReadLine()
    End Sub
End Module
-----------------------------------

Now it is time to test our application.  Run our application side by side.  I have server or host running on the left hand side with green color text and client running on the right with yellow color text.


When the client application is started, it invokes the chatter method on the server. 
  
      myHub.Invoke(Of String)("chatter""Hi!! Server") _
        .ContinueWith(
            Sub(task)
                If task.IsFaulted Then
                    Console.WriteLine("Could not Invoke the server method Chatter: {0}", _
                                      task.Exception.GetBaseException())
                Else
                    Console.WriteLine("Success calling chatter method")
                End If
            End Sub)

You will see “Hi!! Server” value received by the server on the left.  That value is again round tripped to the client and you can see it displayed by the client on the right hand side. 

  myHub.On(Of String)("addMessage", _
            Sub(param)
                Console.WriteLine("Client receiving value from server: {0}", param.ToString())
            End Sub)

Now click on the server console window and press any key.  It will start sending value to the client in real time.  We do this by first getting IHubContext object which knows about all the clients.

            Dim context As IHubContext = GlobalHost.ConnectionManager.GetHubContext(Of MyHub)()
            For x As Integer = 0 To 100
                System.Threading.Thread.Sleep(3000)

                Console.WriteLine("Server Sending Value to Client X: " + x.ToString())
                context.Clients.All.addMessage(x.ToString())
            Next



Now let’s create some more clients that will work with our SignalR Owin Host Console Application. 

SignalR Client WPF Application in VB 
Create a WPF Application in VB and install the following package using Package Manager Console.

>Install-Package Microsoft.AspNet.SignalR.Client.

XAML Side
When you create a WPF application by default MainWindow.xaml file is opened and there paste the following code.  There is a button which will invoke Chatter method on the server. 

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" Loaded="MainWindow_Loaded" >
    <ScrollViewer>
        <StackPanel>
            <Button x:Name="btnShowSignal" Content="Invoke Chatter Method"  Click="btnShowSignal_Click"></Button>
            <TextBlock Name="txtblock_message" Text="{Binding UpdateText}"></TextBlock>
        </StackPanel>
    </ScrollViewer>
</Window>

Codebehind side
On the codebehind side in the MainWindow.xaml.vb we will create a property named UpdateText which will be set everytime our client receives a new text.  In the XAML side, we bind our TextBlock to this UpdateText property so whenever this property is changed it will be shown in the UI.  For all this to happen we have to implement INotifyPropertyChanged Interface. 

--------------------------------------
Imports Microsoft.AspNet.SignalR.Client
Imports System.ComponentModel
Imports Microsoft.AspNet.SignalR.Client.Hubs

Partial Public Class MainWindow
    Inherits Window
    Implements INotifyPropertyChanged
    Public connection As HubConnection = New HubConnection("http://localhost:8080")
    Public myHub As IHubProxy = connection.CreateHubProxy("myHub")

    Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgsHandles Me.Loaded
        DataContext = Me
        connection = New HubConnection("http://localhost:8080")

        myHub = connection.CreateHubProxy("myHub")
        myHub.On(Of String)("addMessage"AddressOf addMessage)
    End Sub

    Async Sub btnShowSignal_Click(sender As Object, e As RoutedEventArgs)
        Await connection.Start()
        Await myHub.Invoke("Chatter""Hello Server")
    End Sub

    Private m_updatetext As String
    Public Property UpdateText() As String
        Get
            Return m_updatetext
        End Get
        Set(ByVal value As String)
            m_updatetext = value
            RaisePropertyChanged("UpdateText")
        End Set
    End Property

    Private Sub addMessage(ByVal sValue As String)
        UpdateText += Environment.NewLine
        UpdateText += sValue
    End Sub
    Private Sub RaisePropertyChanged(prop As String)
        RaiseEvent PropertyChanged(MeNew PropertyChangedEventArgs(prop))
    End Sub
    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgsImplements INotifyPropertyChanged.PropertyChanged
End Class
-----------------------------------------------
Let’s run both of our applications side by side. First Run the Host application and then run the WPF application and put them side by side.  In the screenshot below I have SignalR Owin Host Console Application on the left and WPF application on the right hand side.  Click on the button Invoke Chatter Method which will invoke the server’s Chatter method. 


 As soon as you click on the button it passes the value “Hello Server” to the server and server sends that value back to all the connected clients.  If you want to give it a try then fire up all the SignalR Client Console application too and press any key on the server console window.


After you press any key on the Host application it will send values to two clients as shown below.


And you might be tempted to ask me what about a web application which is the most used application by all of us right. 

SignalR Client Hub Web App consuming Owin Host
Let’s create an empty web application and install Nuget packages as shown below.

>Install-Package Jquery
>Install-Package Microsoft.AspNet.SignalR.JS

Create a simple html page, I have named it as SignalRClientNoProxy.html. You can run the application now to see the output.
-------------------------------------------------
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="Scripts/jquery-2.0.0.min.js"></script>
    <script src="Scripts/jquery.signalR-1.0.1.min.js"></script>    
    <script src="/signalr/hubs" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            var connection = $.hubConnection('http://localhost:8080');

            connection.start();
            var myHub = connection.createHubProxy("myHub");

            $("#broadcast").click(function () {
                myHub.invoke('chatter', $("#msg").val());
            });

            myHub.on('addMessage',function (message) {
                $("#message").append('<li>' + message + '</li>');
            });
        });
    </script>
</head>
<body>
    <div>
        <input id="msg" type="text"/>
        <input type="button" id="broadcast" value="broadcast" />
        <ul id="message">

        </ul>
    </div>
</body>
</html>
------------------------------------------
As a pre-requisite to running our client application on the right we run our server application on the left.


Type something in the textbox on the right window and post something to the server. 


Lets’ run all the applications so far and see how this works.  So one Host and three clients right.

Let now move on to some real world application like Windows Service Application running SignalR Owin Host sending messages to all clients.

SignalR Server Windows Services Application
Now porting this SignalR Owin Host code to window service is easy. Here is the code to do a simple service with signalR. You can check out the code to do a simple windows service from the All-In-One code framework from micrsoft.
------------------------------------------------------
Imports System.Threading
Imports Microsoft.AspNet.SignalR
Imports Microsoft.AspNet.SignalR.Hubs
Imports Microsoft.Owin.Hosting
Imports Owin

Public Class Service1
    Private stopping As Boolean
    Private stoppedEvent As ManualResetEvent
    'global variable context to update clients from everywhere in the service.
    Dim context As IHubContext = GlobalHost.ConnectionManager.GetHubContext(Of MyHub)()
    Dim url As String = "http://localhost:8080"
    Public Sub New()
        InitializeComponent()

        Me.stopping = False
        Me.stoppedEvent = New ManualResetEvent(False)
    End Sub

    Protected Overrides Sub OnStart(ByVal args() As String)
        ' Log a service start message to the Application log.
        Me.EventLog1.WriteEntry("Service is in OnStart.")
        Dim url As String = "http://localhost:8080/"
        Using WebApplication.Start(Of Startup)(url)
            
        End Using
        ' Queue the main service function for execution in a worker thread.
        ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ServiceWorkerThread))
    End Sub


    ''' <summary>
    ''' The method performs the main function of the service. It runs on a 
    ''' thread pool worker thread.
    ''' </summary>
    ''' <param name="state"></param>
    Private Sub ServiceWorkerThread(ByVal state As Object)
        ' Periodically check if the service is stopping.
        Do While Not Me.stopping
            ' Perform main service function here...
            Dim context As IHubContext = GlobalHost.ConnectionManager.GetHubContext(Of MyHub)()
            For x As Integer = 0 To 100
                System.Threading.Thread.Sleep(3000)
                context.Clients.All.addMessage(x.ToString())
            Next
            Thread.Sleep(2000)  ' Simulate some lengthy operations.
        Loop

        ' Signal the stopped event.
        Me.stoppedEvent.Set()
    End Sub

    Protected Overrides Sub OnStop()
        ' Log a service stop message to the Application log.
        Me.EventLog1.WriteEntry("Service is in OnStop.")

        ' Indicate that the service is stopping and wait for the finish of 
        ' the main service function (ServiceWorkerThread).
        Me.stopping = True
        Me.stoppedEvent.WaitOne()
    End Sub
End Class
Public Class Startup
    Public Sub Configuration(ByVal app As IAppBuilder)
        Dim config = New HubConfiguration With {.EnableCrossDomain = True}
        app.MapHubs(config)
    End Sub
End Class
<HubName("myHub")> _
Public Class MyHub
    Inherits Hub
    Public Sub Chatter(param As String)
        Console.WriteLine(param)
        Clients.All.addMessage(param)
    End Sub
End Class
----------------------------------------
You won’t be able to just hit F5 with a windows service, first you will have to install the windows service then you can run your WPF application and then you could see real time output from the windows service.  As I said before the entire source code for all these apps is on my GitHub page.

Thursday, November 29, 2012

Meet my new friend Arduino

My thanksgiving gift to me this year in addition to 3 Kinects was the Arduino UNO R3 which is an open source electronics prototyping platform using Atmel's ATMEGA328P Microcontroller.  I ordered the starter kit from amazon.com which  has few components like jumper wires, Arduino prototyping board, battery connector, USB connector, bread  board and a base stand.

  Now on to next stage to make some LEDs blink.  Some more glamour shots of the board.

Hmm.  But that is not enough, so please show me your back side (no pun intended) I want to see your soldering.
Stay tuned to check out my rookie projects with it.  

Wednesday, November 14, 2012

Create a Default IIS Website using PowerShell

First you will have to import module named "WebAdministration"

PS C:\> Import-Module "WebAdministration"

PS C:\> Get-Command -Module "WebAdministration"

 You can create new website, app pools, bindings with these commandlets. I have combined few commandlets and created my script which does the following:

1.  Does a remote session into a specific computer with specific credentials
2.  Imports Module WebAdministration on that server.
3.  Creates WebAppPool and set's its property.  I have parameter where you can specify .net framework.
4.  Tests physical path of the website if it doesn't exists then it creates one for you.
5.  Create Website with bindings and set's application pool to the one created in step 3.

Here is the script. Enjoy


With PowerShell V3 I do Show-command createdefaultwebsite.ps1 name and it shows me nice form to fill in the details.  I love this feature in V3.


Wednesday, October 24, 2012

Build and Deploy Installer Project using TFS 2010

Every time I search on how to build and deploy visual studio installer projects using TFS 2010 build process I couldn't find nice step by step to it.  But I found a youtube video uploaded by Sangamon Valley .NET User Group which is on Build Automation and Continuous Integration using TFS 2010.   It is very good and I highly recommend if you are new to TFS 2010 build especially. Check it out I have embedded the video below.  If you are looking for Installer project then it is after half way through the video.

Sunday, October 14, 2012

Understanding SignalR and some Knockout.js to do real time communication


In this post, I demonstrate how to create a simple SignalR application using SignalR open source library.  SignalR makes it easy to do real time asynchronous two way communication with server and client.

Open Visual Studio and hit Ctrl+Shift+N to create a new project and click on “ASP.NET Empty Web Application”.  I am using Visual Studio 2012 and .Net Framework 4.5.

Then we are going to install SignalR dlls using Nuget Package Manager.  Right click the project in solution explorer and click on Manage Nuget Packages as shown below.

Or hit Ctrl+Q and type “Nuget” in the quick launch box and click on the first one as shown below.

Hit Ctrl+E and Search for “SignalR” then Click on Install on the first one which is what we need.  Then again install lastest version of jQuery by doing the same thing because SignalR will bring down one or two minor version older.


Hit Ctrl+Shift+A on your keyboard to Add a new class named “myUtilHub.cs” to our solution and add the following code to it.

Add two using statements to add reference to SignalR and SignalR.Hubs and create a public method called sendMessage(). The add code that will talk to our clients will be through Clients class and a dynamic expression which should be a javascript function defined on the individual clients. If you mouseover talk you will see that it is a dynamic expression. The Clients class is available to you when you import SignalR namespace.

Ctrl+Shift+A and add javascript file named myUtil.js to solution and add this function in the extend method of myUtil.js.  The $.extend method of jquery will add properties to our util hub on the client side. You can add as many functions as you want. The server will be able to communicate with these methods via a dynamic expression.
Hit Ctrl+Shift+A and add html page named demo.html and add the following code to it. Now in this function you can get the data that was passed to us and render it inside the div tag of our demo.html.
Right click on demo.html in solution explorer and then click on setup as start page and hit F5 to run the application. You will start seeing the messages as shown below and if you open another browser and type type the same url you will see same output appear in real time.  In IE9 check the document mode, it should be to IE9 for this demo to work.

We can pass data to our sendMessage function like sendMessage("Hello world"); and on the server side we can change our function to accept values from clients like sendMessage(string myvalue).

You can pass .Net object to all clients  and we can access those objects properties in our client side JavaScript.  For example, if you want to pass a DateTime object and access its properties in client side JavaScript then you can do that too.  Change the code of sendMessage() function in our myUtilHub.cs as follows:

In our talk function of hub inside myUtil.js file we will access performance counter's RawValue property to get % Processor Time.
All looks good but there is a problem here.  We don't want to keep scrolling for every new value so we would like to update the UI as the data comes in and I wanted to see if I could do this with the help of Knockout.js or not.  So here it goes.  First of all follow the step to add a Nuget package and then install "Knockout.js" package and add script reference to our demo.html add bindings to it.  Final demo.html
Now change myUtil.js to add ViewModel and add observable properties which will bind to the totalTime in html whenever any change is detected. I commented our all code to append something inside our div tag. Instead we are now using knockout.js to update the UI by passing in ViewModel. Now run the project and see the performance counter update in the browser in real time and this will work in all the browsers at the same time.

Friday, October 5, 2012

Visual Studio 2012 goes search first


Visual Studio 2012 is awesome and my favorite tool that I use daily.  The one thing that I like about VS2012 is how search is implemented more than before and its quick launch textbox on the top right corner.  In this post I want to highlight different places where search box is implemented and where you can  use a shortcut to highlight the box without using a mouse.  

Quick Launch with shortcut Ctrl+Q


In New Project dialog, search using shortcut Ctrl+E 

 Inside Solution Explorer, search for a particular file using shortcut Ctrl+;

      You can not only search for files but you can also search functions within files.  Absolutely magic, see the screenshot below where I searched details and it showed me where Details appeared.  Pretty Cool.

    Inside Team Explorer – Search work items using shortcut Ctrl+’

    Inside Reference Manager – Search using Ctrl+E.  Works for Package Manager dialog too.

        Inside Toolbox, search using well just click it.  Although I would love to have a shortcut to highlight that search box.

     Search Error List,

     Search a Class View

     Search in Code Analysis


If you find any place else a search box inside Visual Studio 2012 then let me know, I would be glad to include it in this post.










Thursday, October 4, 2012

Navigate List of items with Up Down arrow using jQuery in Asp.Net MVC 4 app

This is a continuation from my previous post which demonstrated how to create a simple ASP.NET MVC 4 application with Entity Framework using Adventure Works 2008 Database and Visual Studio 2012.   In this post, I will show you how to navigate our list of products using up and down arrow.  I love how on Google search results page you can navigate search results by using up and down arrow. If you haven’t tried it then give it a try on Google.com.  (There are plenty of examples on this on StackOverflow. However, I have tweaked to make it work for my example.)

We are going to modify our products page so that we can select an individual product using keyboard up/down arrow. After you select a product and hit enter (or return key) it should open up a details page for this particular product. To make this happen we have to do few things.
  1. We want to make products name as hyperlinks to details page so when you click on it, it should show us details page of that particular product. 
  2. Add a details view to show product details 
  3. Wire up the above two with a function in productscontroller.vb page 
  4. Use jQuery to make this thing happen. 
  5. Add Css to indicate which row is highlighted. 
In the Index.vbhtml change the first name as following: Add the following function in our ProductsController.vb

Right click the Details or anywhere in the function above and add another view with following details.

 Run the project and navigate to the following URL.

 Click on the first link and you will see details of it.


Now we have to add this simple javascript to this page.

@section scripts
     <script type="text/javascript">
    $(document).ready(function () {
        var $window = $(window);
        var current_index = -1;
        var $links = $("#plist").find(".detlink");
        var $rows = $("#plist").find(".prow");
        items_total = $links.length;
        //alert($links.length.toString());

        $window.bind('keyup', function (e) {
            if (e.keyCode == 40) {
                dehighlight_row();
                if (current_index + 1 < items_total) {
                    current_index++;
                    highlight_row();
                }
            } else if (e.keyCode == 38) {
                dehighlight_row();
                if (current_index > 0) {
                    current_index--;
                    highlight_row();
                }
            }
           
        });
       
        function highlight_row()
        {
            $rows.removeClass('prow');
            $rows.eq(current_index).addClass('prow-sel');
            //$input.val(current_index);
            $links.eq(current_index).focus();
        }
        function dehighlight_row() {
            $rows.removeClass('prow-sel');
            $rows.eq(current_index).addClass('prow');
            //$input.val(current_index);
            $links.eq(current_index).focus();
        }
    });
</script>
End Section


 From now onward if you want to add scripts to your individual view you should add them in a section as highlighted in yellow in the above code. This will render this tag at the bottom of you rendered page which is a recommended practice and improves performance. And this will load after the jquery scripts have loaded. If you don’t put your javascript script tag inside @section block then a Jscript runtime error will come up if you are debugging using Internet Explorer. If you are debugging using Chrome or Firefox it won't show you a dialog box with this error.

Microsoft JScript runtime error: '$' is undefined 

The above javascript code finds an element with “plist” which is our table and finds all the rows with “prow” class and puts in a $rows variable. Same thing we do will all the links with class “detlink” and put them in $links variable. And from there we just detect up and down arrow by checking the e.keyCode number and highlight and unhighlight that particular row. Once we find a particular row then we will focus that link by using .focus() function of jquery. $links.eq(current_index).focus();

Before finishing do this
1. Add id=”plist” to our table tag.
2. Add class="prow" to tag after for each loop
3. Add following classes to your site.css

.prow{}
.prow-sel {
    border:1px solid green;
}

Add a link to our navigation bar into our _layout.vbhtml page.

<nav>
                        <ul id="menu">
                            <li>@Html.ActionLink("Home", "Index", "Home")</li>
                            <li>@Html.ActionLink("About", "About", "Home")</li>
                            <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                            <li>@Html.ActionLink("Products", "Index", "Products")</li>
                        </ul>
</nav>

Run the project and click on the products page and navigate using up down arrow and then enter to show the details page for the selected product. 

Give your feedback or if you find any bugs or have a better way of doing it, I would be more than happy to know about it.  Thanks.