Jarred Capellman
Putting 1s and 0s to work since 1995
RSS
Twitter
LinkedIn

Sunday, January 25, 2015

A Saturday with SignalR - MVC Serverside Triggering

Posted By Jarred Capellman

Introduction

After having long been on my "todo list" to deep dive on a Saturday, ASP.NET SignalR finally got some attention yesterday. For those unaware, SignalR offers bi-directional communication between clients and servers over WebSockets. For those longtime readers of my blog, I did deep dive into WebSockets back in August 2012 with a WCF Service and Console App, though lost in the mix of several other technologies (MVC, WebAPI, OpenCL etc.) I had forgotten how powerful the technology was. Before I go any further, I highly suggest reading the Introduction to SignalR by Patrick Fletcher.

Fast forward to January 2015, things are even more connected to each other with REST Web Services like WebAPI, the Internet of Things and Mobile Apps from Android, iOS and Windows Phone exploding the last couple of years. Having a specific need for real-time communication from a server to client came up last Friday night for a dashboard in the next big revision of the architecture at work. The idea behind it would be to show off how every request was truly being tracked to who, when and what they were requesting or submitting. This type of audit trail I hadn't ever implemented in any of the previous three major Service Oriented architectures. In addition, presenting the data with Telerik's Kendo UI Data Visualization controls would be a nice way to show not only the audit trail functionality visually outside of the grid listing, but also to show graphs (pictures still tell a thousand words).

As I dove in, the only examples/tutorials I found were showing a simple chat. A user enters his or her name and messages, all the while without any postback the un-ordered list would dynamically update as new messages came in. Pretty neat - but what I was curious about was how one would execute a server side trigger to all the clients. Going back to my idea for enhancing my work project, it would need to be triggered by the WebAPI service, passed to the SignalR MVC app, which in turn the main MVC app would act as the client to display anything triggered originally from the WebAPI Service. So I started diving further into SignalR and in this post go over what I did (if there is a better way, please let me know in the comments). In the coming weeks I will do a follow up post as I expand the functionality to show at a basic level having three seperate projects like the one I will eventually implement at work at some point.

MVC SignalR Server Side Trigger Example

The following code/screenshots all tie back to an example I wrote for this post, you can download it here.

To begin I started with the base Visual Studio 2013 MVC Project (I will assume from here on out everyone is familiar with ASP.NET MVC):
ASP.NET Web Application Visual Studio 2013 Template
Then select the MVC Template:
ASP.NET MVC Template

Add the NuGet package for SignalR (be sure to get the full package as shown in the screenshot, not just the client):
NuGet Manager with SignalR

Upon the NuGet Package completing installation, you will need to add an OWIN Startup File as shown below:
OWIN Startup Class - Visual Studio 2013

This is crucial to SignalR working properly. For posterity here is the Startup.cs in the project I mentioned above:
using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(SignalRMVC.Startup))]
namespace SignalRMVC {
    public class Startup {
        public void Configuration(IAppBuilder app) {
            var config = new HubConfiguration {
                EnableJavaScriptProxies = true
            };

            app.MapSignalR(config);
        }
    }
}
Also new for MVC developers is the idea of a SignalR Hub. You will need to add at least one SignalR Hub class to your project, goto Add and then New Item, scroll down to the SignalR grouping and select the SignalR Hub Class (v2) option as shown in the screenshot below:
OWIN Startup Class - Visual Studio 2013

In the Hub class you define the endpoint(s) for your SignalR Server/Client relationship. For this example, I wrote a simple SendMessage function that accepts a string parameter like so:
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;

namespace SignalRMVC {
    [HubName("systemStatusHub")]
    public class SystemStatusHub : Hub {
        internal static void SendMessage(string logEntry) {
            var context = GlobalHost.ConnectionManager.GetHubContext();

            context.Clients.All.sendData(logEntry);
        }
    }
}
To make things a little cleaner for this example I added a BaseController with a wrapper to the SignalR Hub (mentioned above) adding in a timestamp along with the string passed from the MVC Action like so:
using System;
using System.Web.Mvc;

namespace SignalRMVC.Controllers {
    public class BaseController : Controller {
        internal void RecordVisit(string actionName) {
            SystemStatusHub.SendMessage(String.Format("Someone checked out the {0} page at {1}", actionName, DateTime.Now));
        }
    }
}
With the static wrapper function in place, lets look into the actual MVC Controller, HomeController:
using System.Web.Mvc;

namespace SignalRMVC.Controllers {
    public class HomeController : BaseController {
        public ActionResult Index() {
            RecordVisit("home");

            return View();
        }

        public ActionResult About() {
            RecordVisit("about");

            return View();
        }

        public ActionResult Contact() {
            RecordVisit("contact");

            return View();
        }
    }
}
Nothing unusual for a C# developer, simply passing an indicator based on the title of the Action.

And then in the Index.shtml, it contains the reference to the dynamically generated /signalr/hubs JavaScript file, the JavaScript Connection to the Hub and the handler for what should happen when it receives a message:

Site Activity

    Pretty simple, as the messages come in, append a li to the activityLog ul.

    Finished Product

    Below is a screenshot after clicking around from another browser:

    SignalR in Action

    Again, if you wish to download the complete example you can download it here. In the coming weeks expect at least one more SignalR post detailing a possible solution for common Service Oriented Architectures (seperate MVC, WebAPI and SignalR hosted apps). I hope this helps someone out in the beginning of their SignalR journey.

    Thursday, January 01, 2015

    jcCCL - A new year, a new old project

    Posted By Jarred Capellman

    Some time ago (I want to say 2005) while working on my Infinity Project I was having issues with the large pre-rendered animations I was rendering out in 3ds max (funny to think that 1024x1024@32bpp was at one point huge) akin to the Final Fantasy VII-IX style. After a few animations not only were the files huge, the number of files (they were rendered out to individual frame files) got out of control. Thinking outside the box I started working on my own image format that could contain multiple frames of animation akin to a gif, while also applying what I thought was an ingenious compression approach. Not a hard problem, but when it came to writing a 3ds max or Photoshop plugin to convert targa files to the new format I was overwhelmed (surprisingly I never thought to just write a command line app to batch convert them).

    Fast forward 9 years to last April/May while watching the HBO show Silicon Valley, I was reminded of my earlier compression idea that I never brought to life. Approaching it as a 28 year old having spent the last 8 years doing professional C# as opposed to the 19 year old version of myself proved to be a huge help. I was able to finally implement it to some degree, however any file over 5mb would take several minutes even on my AMD FX-8350, not exactly performance friendly. So I shelved the project until I could come up with a more performance friendly approach and at the same time write it to be supported across the board (Windows Store, Win32, Windows Phone, Android, Linux, MacOSX, FreeBSD).

    Fast forward again to December 21st, 2014 - I had a hunch a slightly revised approach might satisfy the requirements I laid out earlier and finally gave it a name, jcCCL (Jarred Capellman Crazy Compression Library). Sure enough it was correct, and at first I was seeing a 10-15X compression level over zip or rar on every file format (png, mp4, mp3, docx, pdf) I tried. As is the case most of the time, this was due to an error in my compression algorithm not outputting all of the bytes that I uncovered when getting my decompression algorithm working.

    As it stands I have a WPF Win32 application compressing and decompressing files with drag and drop support, however the compression varies from 0 to 10% - definitely not a world changing compression level. However, now that all of the architecture (versioning support, wrappers etc.) are all complete I can focus on optimizing the algorithm and adding in new features like encryption (toying with the idea that it will be encrypted by default). More to come in time on this project, hoping to have a release available soon.