Dreamer. I Love to Build Cool Stuff | Microsoft MVP | Innovator, Architect, Speaker, Blogger | Experience in Microsoft Platforms, .NET, Mobile, Web Apps, Azure, Enterprise Integration, AI | Hacker, Husband, Son, Father
In this post, we’ll explore how to create a simple Xml based markup language for defining shapes for HTML5 Canvas. We’ll achieve this by generating JavaScript code from the Xml definition, and this post is intended to be a pointer towards how you can leverage scaffolding and meta programming to simplify a lot of scenarios. If you don’t have a lot of kids to look after, modify this to create your own version of full fledged CanML (take that name) and let me know
You’ll be able to declare your canvas shapes using XML, for example see how I’m declaring a Heart shape and a Triangle slice. In the heart shape, I’m using absolute co-ordinates, and I’m using variables for triangle slice so that you can draw it anywhere.
And this will be rendered to an HTML5 Canvas as below. This trick is, we are generating the required JavaScript code from the above markup, using the technique I explained in my earlier post – Generating code from simple XML models
What about the Generated JavaScript?
If you are interested to see the JavaScript getting generated from the above Markup, see that below. If you examine the generated code closely along with the xml model we’ve above, you can see that we are following a couple of simple conventions to generate the code from the above markup.
Each <shape/> definition is wrapped as a method, with a canvas parameter (along with other parameters if param element is present)
The type attribute of the Shape
We are having some short cut notations (like to –> moveTo and bcurve-> bezierCurveTo)
If an element has a param attribute, it’ll be rendered as a method (example is moveTo)
If an element has a value attribute, it’ll be rendered as a property (example is
//Method generated
var shapeHeart = function (canvas, fillColor)
{
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.fillStyle=fillColor;
ctx.moveTo(75,40);
ctx.bezierCurveTo(75,37,70,25,50,25);
ctx.bezierCurveTo(20,25,20,62.5,20,62.5);
ctx.bezierCurveTo(20,80,40,102,75,120);
ctx.bezierCurveTo(110,102,130,80,130,62.5);
ctx.bezierCurveTo(130,62.5,130,25,100,25);
ctx.bezierCurveTo(85,25,75,37,75,40);
ctx.fill();
}
}
//Method generated
var shapeTriangleSlice = function (canvas, fillColor,firstX,firstY,delta)
{
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.fillStyle=fillColor;
ctx.moveTo(firstX,firstY);
ctx.lineTo(firstX,firstY+delta);
ctx.lineTo(firstX+delta,firstY);
ctx.fill();
}
}
//Method generated
var allShapes = function (canvas)
{
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.beginPath();
shapeHeart(canvas,'yellow');
shapeTriangleSlice(canvas,'red',200,200,100);
shapeTriangleSlice(canvas,'red',200,200,-100);
}
}
Note that all methods are generated with a canvas input parameter. And now, you may call these methods by linking to the generated CanvasShapes.js script file in your html page – See my index.cshtml ASP.NET MVC razor view where I invoke the allShapes method. Just get your actual canvas element, and pass it to draw, as shown below.
Tell me about the Actual Generation of JS from XML?
The actual generation is super simple – In fact this was just intended to be an sample use case for using the Elastic Object Nuget package for code generation.
To try this out manually,
Create a new ASP.NET MVC Project in Visual Studio.
Install the AmazedSaint.ElasticObject package as explained in my previous post – This will also add an Xml file and a TT (Text template file) to your project
Rename the Xml file to CanvasModel.xml – and copy the above XML code to the same
Rename the TT file CanvasShapes.tt, and add the below T4 code to the TT File
Here is the simple T4 code we are using for generating the JS Code. Oops, the actual conversion code is not even 25 lines, but this is enough to convey the idea, right? You can beef this up further, by adding some support for gradiants, transitions etc to make this full fledged. Keep the MDN Canvas documentation handy.
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ Assembly Name="System.Xml.dll" #>
<#@ Assembly Name="System.Xml.Linq.dll" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ Assembly Name="Microsoft.CSharp.dll" #>
<#@ Assembly name="$(SolutionDir)packages\AmazedSaint.ElasticObject.1.2.0\lib\net40\AmazedSaint.Elastic.dll" #>
<#@ Import Namespace="System.Xml" #>
<#@ Import Namespace="System.Xml.Linq" #>
<#@ Import Namespace="AmazedSaint.Elastic" #>
<#@ Import Namespace="System.Collections.Generic" #>
<#@ Import Namespace="System.Collections" #>
<#@ Import Namespace="AmazedSaint.Elastic.Lib" #>
<#@ output extension=".js" #>
<#
var model=FromFile("CanvasModel.xml");
foreach(var c in model["shape"]) //get all classes
WriteShapeMethod(c);
#>
<#+
//Create an elastic object
private dynamic FromFile(string file)
{
var path= Host.ResolvePath(file);
return XDocument.Load(path).Root.ToElastic();
}
//Write a shape method
private void WriteShapeMethod(dynamic c)
{
#>
//Method generated
var <#= c.name #> = function (<#=c.HasAttribute("params")
?"canvas, " + c.@params :"canvas" #>)
{
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.beginPath();
<#+
var tokens = new System.Collections.Generic.Dictionary<string, string>()
{
{"bcurve","bezierCurveTo"},
{"qcurve","quadraticCurveTo"},
{"line","lineTo"},
{"to","moveTo"},
{"arcTo","arcTo"}
};
foreach (var member in c[null])
{
string mname = tokens.ContainsKey(member.InternalName)
? tokens[member.InternalName] : member.InternalName;
if (member.HasAttribute("params"))
{
if (member.InternalName=="shape")
WriteLine("\t" + member.name + "(canvas," + member.@params + ");");
else
WriteLine("\tctx." + mname + "(" + member.@params + ");");
}
else if (member.HasAttribute("value"))
WriteLine("\tctx." + mname + "=" + member.@value + ";");
else
WriteLine("\tctx." + mname + "();");
}
if (c.HasAttribute("type"))
WriteLine("\tctx." + c.type + "();");
#>
}
}
<#+
}
#>
All right, Happy coding as usual. Enjoy some simple meta coding cookies.
Code generation should be simple, and I wanted to do it by using a simple XML file as my model from with in Visual Studio. So, here is a quick wrapper I’ve created for Xml driven code generation for minimalists/minimal scenarios.
Starting Super Simple XML driven code generation – Now with Nuget
Here we go – this is based on my ElasticObject implementation to generate code using Text Templates (TT/T4), by using simple XML files as a model. It is so simple that it won’t support the entire XML schema - But I’ll live with that for now. So, the steps are simple.
Or you can install this via the Nuget Package manager, it is your choice.
Step 2 – Enjoy
This should add the reference to ElasticObject library, and will add an Xml model file and a T4 template in the Solution Explorer (See the image). The xml file can be your model, and the TT file has a bit of code that wraps the model for generating what ever you need (source code, views, scaffolding etc). You can modify the xml and the TT file. Also, there is a ReadMe-ElasticObject.cs.txt which you can re-name to a CS file and view/run the tests to see the usage of ElasticObject.
What is in the Xml model file and TT generator?
The example model file contains some sample xml, it can be anything (infact, a reasonable subset of xml ;))
So, as you can see, the model can be anything, with in a valid root element. The example just mimics few classes and properties in that. Now, let us have a quick look at the example TT file added by the Nuget package. Don't get afraid, it is some simple T4 syntax - Refresh your T4 Skills from here, Oleg has everything for you to start with the T4 syntax (and much more).
Did I tell you you can use Visual T4 Editor Free edition to reduce the pain when you work with T4 Templates? Get it today from the VS Extensions gallery, otherwise you’ll end up sending hate mails to the guys who created the Visual Studio T4 editor.
In the below code, you could see that we are creating an elastic object from the xml, and then iterating the elements for generating the code – In case you are not familiar with ElasticObject, see my post here – It is just a wrapper dynamic object I created for loosely wrapping stuff like xml. Also, you could see this LIDNUG presentation where Shey is demoing the ElasticObject in between his dynamic talk.
Anyway, here is the T4 code you’ll find in the tt file added by our Nuget package.
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ Assembly Name="System.Xml.dll" #>
<#@ Assembly Name="System.Xml.Linq.dll" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ Assembly Name="Microsoft.CSharp.dll" #>
<#@ Assembly name="$(SolutionDir)packages\AmazedSaint.ElasticObject.1.0.0\lib\net40\AmazedSaint.Elastic.dll" #>
<#@ Import Namespace="System.Xml" #>
<#@ Import Namespace="System.Xml.Linq" #>
<#@ Import Namespace="AmazedSaint.Elastic" #>
<#@ Import Namespace="AmazedSaint.Elastic.Lib" #>
<#@ output extension=".cs" #>
<#
var model=FromFile("ElasticDemoModel.xml");
foreach(var c in model["class"]) //get all classes
WriteClass(c);
#>
<#+
//Create an elastic object
private dynamic FromFile(string file)
{
var path= Host.ResolvePath(file);
return XDocument.Load(path).Root.ToElastic();
}
//Write a class
private void WriteClass(dynamic c)
{
#>
//Class generated
class <#= c.name #>
{
<#+
foreach(var p in c["property"])
WriteProperty(p);
#>
}
<#+
}
//Write a Property
private void WriteProperty(dynamic p)
{
#>
public <#= p.type #> <#= p.name #> {get;set;}
<#+
}
#>
And you guessed it, the generated file is here.
//Class generated
class MyClass1
{
public string MyProperty1 {get;set;}
public string MyProperty2 {get;set;}
}
//Class generated
class MyClass2
{
public string MyProperty1 {get;set;}
public string MyProperty2 {get;set;}
}
Note that this requires C# dynamic support, and hence targets the .NET 4.0 runtime – So if you want to have code generation in other platforms with out dynamic support, add a .NET 4.0 project, keep your models and TT/T4s there, and add/link the generated files to other projects. This example just shows C# code generation from the model, but you can imagine what all things you can do
This weekend hack is a small Kinect application - Kibloc is a physical object counter/tracker using Kinect.
Update As Of Feb 1 2012: This article is explaining Version 1.0 Beta 2 APIs. How ever, now the Official 1.0 Kinect SDK For Windows is available, and there are changes from the Beta 2 API.
Kinect for Windows SDK (Download) is pretty intuitive (I’m using Version 1.0 Beta 2 for this, so if you want to test this you should use Beta 2 APIs which is still available as a separate download and NOT the Version 1.0 APIs), and you may use the same to develop pretty cool applications using Microsoft Kinect. In this post, we’ll be focusing on implementing a quick real time blob counter using Kinect depth data, for counting and tracking objects in front of the sensor. This is a basic demo, but as you can imagine, this has got a couple of pretty hot real life use cases. As a heads up, the source code is at http://kibloc.codeplex.com/ and keep it handy when you read along. Ensure you’ve the NuGet Packages in packages.config
Here is the video that demonstrates real time, distance based blob tracking.
In the video, the image drawing for the blob highlight is a bit slow, this is because I’m drawing it on top of the color image as discussed below. For actual games/calculations, you don’t need the drawing on top of the color image/bitmap.
So, let us develop this. The steps involved are pretty simple.
Initializing Kinect
Get the depth image, and slice the depth frame to draw pixels with in the range to form a gray scale image
Pass this image to the blob detection algorithm
Find the convex hull/edges/quadrilateral
Draw the same on the color image from the video frame
Introduction to Kinect API
Kinect API allows you to work with the Kinect camera’s image/video stream, almost similar to a web cam. Apart from the RGB Video camera, Kinect has got a depth sensor as well., which gives you information about the distance of an object in front of the device - and you can leverage the Video data and Depth data together to detect objects using Kinect. Kinect also exposes built in support for Skeletal tracking. The classes for working with Video, Depth and Skeletal Tracking resides in the namespace Microsoft.Research.Kinect.Nui. You can access the Kinects connected to the device via the Runtime.Kinects enumeration, and can access the Depth, Video and Skeletal tracking data by handling the DepthFrameReady, VideoFrameReady and SkeletalFrameReady events of a connected Kinect object. In the below example you could see that we are accessing the Depth data from Kinect.
Additionally, you can also use the Audio features of Kinect, leveraging classes available under the namespace Microsoft.Research.Kinect.Audio.
That is it for an interesting, and I suggest you should go through the SDK Quick starts and samples here at Coding 4 Fun if you need to learn more about how to work with the SDK in detail. The API is intuitive and super easy, but I suggest you may go through these videos to kick start.
The first step is to initialize Kinect, so here is the self explanatory code.
// If you don't make sure the Kinect is plugged in and working before trying to use it, the app will crash
if (Runtime.Kinects.Count > 0)
{
runtime = Runtime.Kinects[0];
runtime.Initialize(RuntimeOptions.UseColor | RuntimeOptions.UseDepth);
runtime.DepthFrameReady += (s, e) =>
{
// Use depth data
};
runtime.VideoFrameReady += (s, e) =>
{
//Use video data
};
runtime.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.Depth);
runtime.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
}
else
MessageBox.Show("Oops, please check if your Kinect is connected?");
Basically, you may see that we are initializing the Kinect run time by passing the flags UseColor and UseDepth, so that we can consume the DepthStream and VideoStream later. The event handlers are attached to DepthFrameReady and VideoFrameReady events as shown above.
Get the depth image for a range
Kinect depth data is just an array of bytes, where each pixel is represented with two bytes (16 bits). Each pixel in the depth data provides distance of a pixel from the sensor, instead of color information as in a normal bitmap pixel. You can either specify Kinect to provide you the raw depth data (ImageType.Depth) or to provide you depth data along with player index (ImageType.DepthAndPlayerIndex) when you initialize the DepthStream (see the above code). You can read this iProgrammer article if you are interested to learn more about the Depth data, in detail.
Basically, what we do in the below method is to walk through the PlanarImage (raw byte array) for Depth data, and create a bitmap with 4 bytes per pixel (Red, Blue, Green and Alpha) – where Red, Blue and Green values will be the same value to form a gray scale image. The value is any number between 0 to 255, based on the distance of a pixel.
/// <summary>
/// Credits due:
/// Portions of code below from
/// (1) http://www.codeproject.com/Articles/317974/KinectDepthSmoothing though I'm not really smoothing here :)
/// (2) http://stackoverflow.com/questions/94456/load-a-wpf-bitmapimage-from-a-system-drawing-bitmap
///
/// -- Anoop
/// </summary>
public static BitmapSource SliceDepthImage(this ImageFrame image, int min=20, int max=1000)
{
int width = image.Image.Width;
int height = image.Image.Height;
var depthFrame = image.Image.Bits;
// We multiply the product of width and height by 4 because each byte
// will represent a different color channel per pixel in the final iamge.
var colorFrame = new byte[height * width * 4];
// Process each row in parallel
Parallel.For(0, 240, depthRowIndex =>
{
// Within each row, we then iterate over each 2 indexs to be combined into a single depth value
for (int depthColumnIndex = 0; depthColumnIndex < 640; depthColumnIndex += 2)
{
var depthIndex = depthColumnIndex + (depthRowIndex * 640);
// Because the colorFrame we are creating has twice as many bytes representing
// a pixel in the final image, we set the index to be twice of the depth index.
var index = depthIndex * 2;
// Calculate the distance represented by the two depth bytes
var distance = CalculateDistanceFromDepth(depthFrame[depthIndex], depthFrame[depthIndex + 1]);
// Map the distance to an intesity that can be represented in RGB
var intensity = CalculateIntensityFromDistance(distance);
if (distance > min && distance < max)
{
// Apply the intensity to the color channels
colorFrame[index + 0] = intensity; //blue
colorFrame[index + 1] = intensity; //green
colorFrame[index + 2] = intensity; //red
colorFrame[index + 3] = 255; //alpha
}
}
});
Once the depth image is created, we pass it over to the Blob detector to detect the blobs and high light the same.
Blob Detection and Highlighting
For blob detection, I’m using the Excellent AForge library. The BlobCounter class takes the above image, and calculate the edges/rectangles of the blobs in the image. Here is an expansion of our earlier DepthFrameReady and ImageFrameReady events, you can see that we are creating a sliced depth image based on the slider values, and creating a depth frame image bitmap and a color frame image bitmap, and passes both of them to the blob detector. We are also specifying what type of high lighting to be used by the detector, based on the combo box the user has selected.
runtime.DepthFrameReady += (s, e) =>
{
if (colorFrame == null) return;
if (sliderMin.Value > sliderMax.Value)
sliderMin.Value = sliderMax.Value;
detector.Highlighting = (HighlightType) cmbHighlight.SelectedIndex;
txtInfo.Text = detector.BlobCount + " items detected..";
txtDistance.Text = "Detecting objects in the range " + sliderMin.Value + " and " + sliderMax.Value + " mm";
//Depth frame bitmap
var depthFrame=e.ImageFrame.SliceDepthImage((int)sliderMin.Value,(int)sliderMax.Value);
var depthBmp =depthFrame.ToBitmap();
//Color frame bitmap
var colorBmp = colorFrame.ToBitmapSource().ToBitmap();
//Detect blobs using depthBmp, draw high lights to colorBmp
var outBmp=detector.ProcessImage(depthBmp,colorBmp);
//Draw the output high lighted color image
this.ImageColor.Source = outBmp.ToBitmapSource();
depthBmp.Dispose();
colorBmp.Dispose();
outBmp.Dispose();
};
runtime.VideoFrameReady += (s, e) =>
{
//colorFrame is a global variable
colorFrame = e.ImageFrame;
};
The following ProcessImage method in our BlobDetector class basically uses the AForge library to do the detection based on depth image.
After detection, we are drawing the high lights back to the color image which results in the image above. This code is mostly based on the AForge blob detection sample.
// Set image to display by the control
public Bitmap ProcessImage(Bitmap depthImage, Bitmap colorImage)
{
leftEdges.Clear();
rightEdges.Clear();
topEdges.Clear();
bottomEdges.Clear();
hulls.Clear();
quadrilaterals.Clear();
this.image = AForge.Imaging.Image.Clone(depthImage, PixelFormat.Format24bppRgb);
imageWidth = this.image.Width;
imageHeight = this.image.Height;
blobCounter.ProcessImage(this.image);
blobs = blobCounter.GetObjectsInformation();
//Let us resize the color image to the size of depth image
ResizeNearestNeighbor filter = new ResizeNearestNeighbor(depthImage.Width, depthImage.Height);
var outImage = filter.Apply(colorImage);
//Let use flip the color image to match the depth image
outImage.RotateFlip(RotateFlipType.RotateNoneFlipX);
BlobCount = blobs.Count();
GrahamConvexHull grahamScan = new GrahamConvexHull();
foreach (Blob blob in blobs)
{
List<IntPoint> leftEdge = new List<IntPoint>();
List<IntPoint> rightEdge = new List<IntPoint>();
List<IntPoint> topEdge = new List<IntPoint>();
List<IntPoint> bottomEdge = new List<IntPoint>();
// collect edge points
blobCounter.GetBlobsLeftAndRightEdges(blob, out leftEdge, out rightEdge);
blobCounter.GetBlobsTopAndBottomEdges(blob, out topEdge, out bottomEdge);
leftEdges.Add(blob.ID, leftEdge);
rightEdges.Add(blob.ID, rightEdge);
topEdges.Add(blob.ID, topEdge);
bottomEdges.Add(blob.ID, bottomEdge);
// find convex hull
List<IntPoint> edgePoints = new List<IntPoint>();
edgePoints.AddRange(leftEdge);
edgePoints.AddRange(rightEdge);
List<IntPoint> hull = grahamScan.FindHull(edgePoints);
hulls.Add(blob.ID, hull);
List<IntPoint> quadrilateral = null;
// find quadrilateral
if (hull.Count < 4)
{
quadrilateral = new List<IntPoint>(hull);
}
else
{
quadrilateral = PointsCloud.FindQuadrilateralCorners(hull);
}
quadrilaterals.Add(blob.ID, quadrilateral);
// shift all points for vizualization
IntPoint shift = new IntPoint(1, 1);
PointsCloud.Shift(leftEdge, shift);
PointsCloud.Shift(rightEdge, shift);
PointsCloud.Shift(topEdge, shift);
PointsCloud.Shift(bottomEdge, shift);
PointsCloud.Shift(hull, shift);
PointsCloud.Shift(quadrilateral, shift);
}
//Method to draw the high lights, just see the full source code
DrawHighLights(outImage);
return outImage;
}
Conclusion
In this post, we explored how to create a blob detector and object counter using Kinect. As of now, Kinect’s built in tracking feature is limited just to Skeletal tracking, but you can use libraries like AForge.net and openCV to leverage Kinect for more out of the box scenarios. Thanks to my kiddo for lending me her dolls for the demo . Also, follow me in twitter. And here are few more posts on a similar taste.
Happy New Year, this is my first post in 2012. I’ll be sharing few awesome learning resources I’ve bookmarked, and will be pointing out some specific computer/programming related courses I've found interesting from these resources.
Also, thought about saving this blog post for my kids as well - instead of investing in these Child education schemes (though they are too small as of today, 2 years and 60 days respectively ). Anyway, personally my new year resolution is to see as much videos from this course collections (assuming I can find some free time in between my regular job && changing my babies diapers).
1 – Khan Academy
As I mentioned some time back, you and your kids are missing some thing huge if you havn’t heard about Khan Academy. It is an awesome learning resource, especially if you want to re-visit your basics in Math, Science etc.
With a library of over 2,600 videos covering everything from arithmetic to physics, finance, and history and 268 practice exercises, they're on a mission to help you learn what you want, when you want, at your own pace
From the computer science perspective, checkout these introduction to Computer Science. Click the Lectures tab, and most lectures are available via Youtube, iTunes and even as WMV.
Xavier recently shared a bunch of new free online courses that Stanford will be starting soon. These courses are starting by this February 2012, why not sign up.
And most of them are available via Youtube, iTunes etc.
These are few resources I explored and book marked for future reference, and I’m pretty sure there are lot more out there that I’ve skipped/missed. For instance, this awesome list of Computer Science papers that I came across the other day. Please share, and enjoy. Happy Coding!!
Real time data syncing across user views *was* hard, especially in web applications. Most of the time, the second user needs to refresh the screen, to see the changes made by first user, or we need to implement some long polling that fetches the data and does the update manually.
Now, with SignalR and Knockout, ASP.NET developers can take advantage of view model syncing across users, that’ll simplify these scenarios in a big way, with minimal code. This post discusses how to implement a real time to-do pad, which will sync data across users accessing the application. This means, users can make changes to their tasks (add/remove/update etc), and other users will see the changes instantly. The focus is on the technique, I’m not trying to build a fabulous user experience here.
I know we are tired with To-do examples, but now let us build a To-do application that can sync tasks between you and your wife (or your team mates) in real time, with full CRUD support, and persistence. And yes, we’ll keep the code minimal, and maintainable using a proper View Model (Oh, is that possible in JavaScript?).
So, see this video, and here you can see the changes you apply to the tasks in one screen (adding, deleting, updating etc) you can see that the data is getting synced across multiple users.
We’ll be using KnockoutJs for maintaining a View Model, and will be syncing the View Model across users using SignalR. If you are not familiar with Knockout and SignalR, we’ll have a quick look at both of them on the way.
First Things First
To start with, let us create a new ASP.NET MVC 3.0 application. Create an empty project, I’ve ASP.NET MVC 3 tools update installed. Once you’ve the ASP.NET MVC project created, bring up the Nuget console (View->Other Windows-> Package Manager console), and install the Nuget packages for Knockout and SignalR.
install-package knockoutjs
And SignalR
install-package signalr
Also, do install Entity Framework latest version if you don't have the same, so that we can use the Code first features
Install-Package EntityFramework
If you are already familiar with Knockout and SignalR, you may skip the next two titles and go directly to 'Building KsigDo' section.
Knockout
Knockout Js is an awesome Javascript library that allows you to follow the MVVM convention, to bind your User controls to a JavaScript view model. This is pretty cool, because it allows you to build rich UIs pretty easily, with very minimal code. Here is a quick example that shows how you can bind your HTML elements to a Javascript view model.
Here is a very simple view model.
// This is a simple *viewmodel*
var viewModel = {
firstName: ko.observable("Bert"),
lastName: ko.observable("Bertington")
};
// Activates knockout.js
ko.applyBindings(viewModel);
The attributes are of type ko.observable(..), and if you want to convert the viewModel to an object (where you can send over the wire), you can easily do that using ko.toJS(viewModel). Now, let us bind the above view model to a view. The binding happens in the data-bind attribute, you may see that we are binding the value of the textbox to the firstname and last name variables. When you call ko.applyBindings, Knockout will do the required wiring so that the view model properties are synced with the target control's property values.
<!-- This is a *view* -->
<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
KnockoutJs is pretty easy to learn, the best way to start is by going through the interactive tutorial hosted by Knockout guys here at http://learn.knockoutjs.com/.
Update: Found that Shawn has wrote a comprehensive post on Knockout, Read that as well
SignalR
SignalR is the “greatest thing since sliced bread” that happened for Microsoft developers recently. (To know why, you can read by post “HTML5 is on a killer spree, may kill HTTP next at least partially”. Anyway, SignalR is an Async signaling library for ASP.NET to help build real-time, multi-user interactive web applications. If you heard about Node, Backbone, Nowjs etc recently, you know what I’m talking about. If not, you’ll know pretty soon though.
The easiest starting point to understand SignalR is, by having a look at the Hub Quickstart example. Have a look at that example and come back.
You can inherit your Hub at the server side from SignalR.Hubs.Hub – and SignalR will generate the necessary light weight Javascript proxies at the client side so that you can make calls to your hub over the wire, even with support for typed parameters. Not just that. SignalR also provides dynamic “Clients” and “Caller” objects in your hub, so that you can invoke a client side method written in Javascript directly via your code in the server side. Pretty smart. And SignalR hides the entire implementation under its nice little APIs.
Building The KsigDo App
Now, let us go ahead and build our KsigDo app. Let us put together the bits step by step.
Task Model For Persistance Using Entity Framework Code First
In you ASP.NET MVC application, go to the Models folder, and add a new code first model file. Our model is very minimal, and as you can see, we have a taskId and a title for a task, and few validation rules defined, like title's length. Also, the completed property decides whether the task is a completed one or not.
public class KsigDoContext : DbContext
{
public DbSet<Task> Tasks { get; set; }
}
public class Task
{
[Key]
public int taskId { get; set; }
[Required] [MaxLength(140)] [MinLength(10)]
public string title { get; set; }
public bool completed { get; set; }
public DateTime lastUpdated { get; set; }
}
The DbContext and DbSet classes used above are provided as part of the EF4 Code-First library. Also, we are using the attributes like Key, Required etc for data annotations, for basic validation support.
TaskHub For Basic Operations
Create a new folder named 'Hubs' in your ASP.NET MVC project, and add a new TaskHub.cs file (No, we are not using Controllers now). And yes, you can place your Hubs any where. Here is our TaskHub, inherited from SignalR.Hubs.Hub class. You may see that we are using this Hub to perform most of the CRUD operations in our Task Model.
public class Tasks : Hub
{
/// <summary>
/// Create a new task
/// </summary>
public bool Add(Task newTask)
{
try
{
using (var context = new KsigDoContext())
{
var task = context.Tasks.Create();
task.title = newTask.title;
task.completed = newTask.completed;
task.lastUpdated = DateTime.Now;
context.Tasks.Add(task);
context.SaveChanges();
Clients.taskAdded(task);
return true;
}
}
catch (Exception ex)
{
Caller.reportError("Unable to create task. Make sure title length is between 10 and 140");
return false;
}
}
/// <summary>
/// Update a task using
/// </summary>
public bool Update(Task updatedTask)
{
using (var context = new KsigDoContext())
{
var oldTask = context.Tasks.FirstOrDefault(t => t.taskId == updatedTask.taskId);
try
{
if (oldTask == null)
return false;
else
{
oldTask.title = updatedTask.title;
oldTask.completed = updatedTask.completed;
oldTask.lastUpdated = DateTime.Now;
context.SaveChanges();
Clients.taskUpdated(oldTask);
return true;
}
}
catch (Exception ex)
{
Caller.reportError("Unable to update task. Make sure title length is between 10 and 140");
return false;
}
}
}
/// <summary>
/// Delete the task
/// </summary>
public bool Remove(int taskId)
{
try
{
using (var context = new KsigDoContext())
{
var task = context.Tasks.FirstOrDefault(t => t.taskId == taskId);
context.Tasks.Remove(task);
context.SaveChanges();
Clients.taskRemoved(task.taskId);
return true;
}
}
catch (Exception ex)
{
Caller.reportError("Error : " + ex.Message);
return false;
}
}
/// <summary>
/// To get all the tasks up on init
/// </summary>
public void GetAll()
{
using (var context = new KsigDoContext())
{
var res = context.Tasks.ToArray();
Caller.taskAll(res);
}
}
}
The Clients and Caller properties are provided by SignalR as part of the Hub class definition. Surprise, these are dynamic objects that you can use conceptually to invoke a client side method written in JavaScript. SignalR does the plumbing using long polling or web sockets or what ever, and we don’t care. Also, as I mentioned earlier, SignalR will generate a client side proxy hub to invoke methods in our above written TaskHub, and we’ll soon see how to use this. For example, when a client invokes GetAll method in the above Hub during initialization, that client invoking the GetAll method (Caller) will get a callback to it’s taskAll JavaScript method, with all the existing tasks.
In the same way, assuming that our Client hub has Javascript methods like taskUpdated, taskAdded, taskRemoved etc – we are invoking those methods using the ‘Clients’ dynamic object, so that when ever an update, add or delete is happening, this information is broad casted all the clients connected right now.
The Main View
Now, let us go ahead and create our client side. Add a 'Home' controller, and an 'Index' action. Create a new 'Index' view. Also, just make sure you’ve the necessary Javascript Script wirings to import Knockout and SignalR libraries (See the code).
Our Index page has got a couple of view models, and a bit of HTML (view). For view models, we’ve a taskViewModel, and a taskListViewModel, as shown below. You may note that our taskViewModel is having almost the same properties as we have in our actual Task model, so that SignalR can manage the serialization/mapping pretty easily when ever we call the methods in our TaskHub.
You can see that in taskListViewModel, we are accessing the $connection.tasks proxy which provides a proxy object to access methods in our TaskHub. Also, we are attaching methods like tasksAll, taskUpdated etc to the $connection.tasks via the this.hub pointer, and these methods are ‘invoked’ from the TaskHub class as we’ve seen earlier to virtually ‘push’ data to the clients.
$(function () {
//---- View Models
//Task View Model
function taskViewModel(id, title, completed, ownerViewModel) {
this.taskId = id;
this.title = ko.observable(title);
this.completed = ko.observable(completed);
this.remove = function () { ownerViewModel.removeTask(this.taskId) }
this.notification = function (b) { notify = b }
var self = this;
this.title.subscribe(function (newValue) {
ownerViewModel.updateTask(ko.toJS(self));
});
this.completed.subscribe(function (newValue) {
ownerViewModel.updateTask(ko.toJS(self));
});
}
//Task List View Model
function taskListViewModel() {
//Handlers for our Hub callbacks
this.hub = $.connection.tasks;
this.tasks = ko.observableArray([]);
this.newTaskText = ko.observable();
var tasks = this.tasks;
var self = this;
var notify = true;
//Initializes the view model
this.init = function () {
this.hub.getAll();
}
//Handlers for our Hub callbacks
//Invoked from our TaskHub.cs
this.hub.taskAll = function (allTasks) {
var mappedTasks = $.map(allTasks, function (item) {
return new taskViewModel(item.taskId, item.title,
item.completed, self)
});
tasks(mappedTasks);
}
this.hub.taskUpdated = function (t) {
var task = ko.utils.arrayFilter(tasks(), function (value) { return value.taskId == t.taskId; })[0];
notify = false;
task.title(t.title);
task.completed(t.completed);
notify = true;
};
this.hub.reportError = function (error) {
$("#error").text(error);
$("#error").fadeIn(1000, function () {
$("#error").fadeOut(3000);
});
}
this.hub.taskAdded = function (t) {
tasks.push(new taskViewModel(t.taskId, t.title, t.completed, self));
};
this.hub.taskRemoved = function (id) {
var task = ko.utils.arrayFilter(tasks(), function (value) { return value.taskId == id; })[0];
tasks.remove(task);
};
//View Model 'Commands'
//To create a task
this.addTask = function () {
var t = { "title": this.newTaskText(), "completed": false };
this.hub.add(t).done(function () {
console.log('Success!')
}).fail(function (e) {
console.warn(e);
});
this.newTaskText("");
}
//To remove a task
this.removeTask = function (id) {
this.hub.remove(id);
}
//To update this task
this.updateTask = function (task) {
if (notify)
this.hub.update(task);
}
//Gets the incomplete tasks
this.incompleteTasks = ko.dependentObservable(function () {
return ko.utils.arrayFilter(this.tasks(), function (task) { return !task.completed() });
}, this);
}
var vm = new taskListViewModel();
ko.applyBindings(vm);
// Start the connection
$.connection.hub.start(function () { vm.init(); });
});
When ever a taskViewModel is created, the instance of taskListViewModel will be passed as it’s ownerViewModel, so that we can invoke the updateTask method of taskListViewModel when ever the current task’s properties are changing. In taskListViewModel, we also have methods like addTask, removeTask etc, which are bound directly to our “View”.
We are creating a new instance of taskListViewModel, and then calling Knockout to do the job of applying bindings with the view. Have a look at the “View” part.
If you look below the Add Task header, you’ll see that we are binding the textbox’s value to the ‘newTaskText’ property of our taskListViewModel, and the form submit to the addTask method in the taskListViewModel. The <ul> is bound to the tasks property of the view model. If you see, tasks property of taskListViewModel is a koObservableArray, which is almost like an ObservableCollection that notifies the bound controls when ever items are inserted/removed in the array.
Adding and Removing items
Have a look at the addTaskMethod in the taskListViewModel, you’ll see that we are creating a new task, and then invoking the ‘add’ method of the ‘hub’, which internally calls the TaskHub’s Add method in the server. In the TaskHub’s Add method, you’ll see that we are broadcasting the added task to all the clients by invoking the taskAdded method in the client side back – and there we are updating the ‘items’ observable array, so that Knockout will internally manage the rendering of a new <li> under the <ul> based on the data template ‘tasktemplate’ (see the above view code where we have the tasktemplate.
Delete also works in the same way, you can see the ‘x’ button is bound to the remove method of each individual taskViewModel, which internally calls the taskListViewModel’s removeTask method to invoke the Remove method in TaskHub using the hub proxy, and from there, the taskRemoved will be invoked on all the clients, where we actually remove the item from the items collection.
Updating an Item:
Once an item is bound to the template, please note that we are subscribing to the change events of a task in taskViewModel. When ever a property changes, we call the updateTask method in the ownerViewModel, which again calls hub’s update method which sends the task to our TaskHub’s update method – thanks to the wiring from SignalR. There, we try to save the item, and if everything goes well, the updated item will be broadcasted from the TaskHub to all clients, by invoking the taskUpdated Javascript method we attached to the hub, where we actually does the updates the properties of the item in all clients.
Conclusion
Surprise, we are done. Very minimal code, very little effort, Great results. Thank you ASP.NET, SignalR, Entity Framework and Knockout. And that is why I love .NET . Happy Coding, but follow me in twitter @amazedsaint and subscribe to this blog.
You may also like these articles on a similar taste.
We’ve already seen HTML5 killing few technologies on the presentation side – Adobe Just killed Flash for Mobile, and Microsoft ‘Positioned’ Silverlight as a tool for LOB apps and Phone apps instead of a cross platform presentation layer.
As most organizations are now focusing on HTML5 as part of their next gen strategy for what ever reasons (mainly cross platform), it is pretty obvious that there is going to be wide spread adoption from all major user agents – and more importantly, a lot more tooling and frameworks will evolve for developing HTML5 applications (You might have already explored previews like Expression Blend for HTML5 if you are in the Microsoft World, along with improved support for HTML5 in VS). The evolution of HTML5 will definitely bring in a radical shift in the way we develop web applications as we have already seen – and a nice little part of the parcel is Web sockets - which allows you to implement full duplex TCP based communication between the user agent (browser) and the server.
The problem with HTTP and existing server stacks
Here is a short description of HTTP from W3C
The Hypertext Transfer Protocol (HTTP) is an application-level protocol for distributed, collaborative, hypermedia information systems. It is a generic, stateless, protocol which can be used for many tasks beyond its use for hypertext, such as name servers and distributed object management systems, through extension of its request methods, error codes and headers [47]. A feature of HTTP is the typing and negotiation of data representation, allowing systems to be built independently of the data being transferred.
HTTP works in a request/response way – The client should always initiate a request to obtain the data, and in other words, the server can never push data real time to client. A common work around is to use HTTP long polling, where the client makes a request, and the server holds the request till some data is available, and pass it back to the client. I believe from Http 1.1 onwards, persistent connections are the default behavior of the HTTP connection anyway – though the response/request HTTP model don’t allow the server to do real-time pushes.
WebSocket is a technology providing for bi-directional, full-duplex communications channels, over a single Transmission Control Protocol (TCP) socket. It is designed to be implemented in web browsers and web servers but it can be used by any client or server application. The WebSocket API is being standardized by the W3C and the WebSocket protocol is being standardized by the IETF.
With web sockets, which are fully duplex, you have some thing state full, which will allow you to build web applications which can satisfy real time requirements. This means better user experience, better speed, and overall better productivity. We’ll see a new range of web applications emerging, including more sophisticated games and better real collaboration tools. We’ll definitely see more matured and domain specific light weight RPC frameworks for servers and clients (As of now, I think frameworks like NowJs/Socket.IO on top of Node and SignalR on to of IIS already has this in their implementation/roadmap in a general way - to wrap web sockets and has a fall back strategy on HTTP long polling if the client is not supporting web sockets yet).
According the Web Socket API spec, when a web socket connection is made,
The headers to send appropriate cookies must be a Cookie header whose value is the cookie-string computed from the user's cookie store and the URL url; for these purposes this is not a "non-HTTP" API.
Anyway, most of the current server stacks and related programming models, including LAMP, IIS/ASP.NET etc is modeled around the normal request/response HTTP stack -and once the focus on Web sockets increases, they need to optimize themselves to handle concurrent connections simultaneously with out affecting the performance. A new age web server may be almost like a re-labeled IRC server which can handle a number of real time connections simultaneously (On contrary, you may also argue that HTML5 web sockets may make IRC servers obsolete as well).
Web Socket API specifications are not yet finalized. And as of now, based on http://caniuse.com – the following client side platforms are supporting Web Sockets specs. Between, I use http://caniuse.com often to see the platform adoption of HTML5 APIs and Semantics.
I think, to some extent, this means a radical shift in the way we write web applications which need real time features. More importantly, you can bend the web in a better way – because you’ve access to a transport layer protocol (TCP) on top of which you can build your own custom/domain centric protocols, instead of getting constrained with the application level HTTP protocol. Also, I am pretty sure that most of the client side agents other than web browsers will also start supporting web sockets in no time.
A Quick word on Server Side Events
As you read this far, it might be interesting to note that HTML5 specifications has another API named server side events (SSE), which allows you to Push data from server to client via an HTTP channel.
This specification defines an API for opening an HTTP connection for receiving push notifications from a server in the form of DOM events. The API is designed such that it can be extended to work with other push notification schemes such as Push SMS.
Anyway, Web Sockets are getting more attraction because it provides more control as it is on top of TCP, and more importantly, it is bidirectional. And what ever you can do with SSE can be implemented using Web Sockets, with a bit of custom code.
Here are few links to follow.
Checkout this example of Web Sockets - This is a quick example that shows how I’m streaming WPF windows over web sockets to a browser, to draw it in a canvas
Happy Coding, but beware, HTML5 is just near your door. Chances are that, pretty soon, almost half of the things you do today with classic HTTP stack will be replaced with wrapper implementations like NowJs or SignalR.
This post is about implementing Chain Of Responsibility design pattern, and few possible extensions to the same. If you are new to design patterns, I suggest you should start with Practically Applying Design Patterns – Thought Process
Coming back to Chain of Responsibility - If you have a scenario where you need to chain multiple handlers to handle an incoming request or command, you better use Chain Of Responsibility.
A typical example is your girlfriend requesting you something – If she is requesting/commanding you something like “Do you want to come with me for my best friend’s Bachelorette party?”, you will handle it directly. But if she is requesting/commanding you some thing like “Buy me a Porsche”, you say “Sorry Honey, I don’t have the money. Better you ask your dad for this, I’ll call him for you” –i.e, you pass the request to the next handler, in this case your girl friend’s Father. To sum up, in the above example, your girl friend is the client who is making the request, and you and your future father-in-law are handlers/approvers who handle/approve her requests. If you cannot handle it, you pass that responsibility to the next handler/approver in the chain.
A Minimal Example
To consider a more formal example, assume a scenario where you’ve a banking system, and you want to implement some kind of Loan approval. The customer may request a loan, and if it is below a specific amount, the cashier may approve it directly. If it is above the specified amount, he might pass the request to his manager for approval.
So you may use Chain Of Responsibility implementation to hand over the request/command to the correct approver. For an example, consider this implementation of the above Bank account scenario. Our business rule is something like, a cashier can approve the request if the amount is lesser than 1000 $$, other wise the approval should be passed to the manager. The manager can approve the request if the amount is lesser than 10,000 $$.
Concrete handlers like Cashier and Manager implements this
Has a reference to the successor to pass the request
Program – The main driver
To the code
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DesignPatternsCof
{
//Request
class LoanRequest
{
public string Customer { get; set; }
public decimal Amount { get; set; }
}
//Abstract Request Handler
interface IRequestHandler
{
string Name { get; set; }
void HandleRequest(LoanRequest req);
IRequestHandler Successor { get; set; }
}
//Just an extension method for the passing the request
static class RequestHandlerExtension
{
public static void TrySuccessor(this IRequestHandler current, LoanRequest req)
{
if (current.Successor != null)
{
Console.WriteLine("{0} Can't approve - Passing request to {1}", current.Name, current.Successor.Name);
current.Successor.HandleRequest(req);
}
else
{
Console.WriteLine("Amount invaid, no approval given");
}
}
}
//Concrete Request Handler - Cachier
//Cachier can approve requests upto 1000$$
class Cashier : IRequestHandler
{
public string Name { get; set; }
public void HandleRequest(LoanRequest req)
{
Console.WriteLine("\n----\n{0} $$ Loan Requested by {1}",
req.Amount, req.Customer);
if (req.Amount<1000)
Console.WriteLine("{0} $$ Loan approved for {1} - Approved by {2}",
req.Amount,req.Customer, this.Name);
else
this.TrySuccessor(req);
}
public IRequestHandler Successor { get; set; }
}
//Concrete Request Handler - Manager
//Manager can approve requests upto 10000$
class Manager : IRequestHandler
{
public string Name { get; set; }
public void HandleRequest(LoanRequest req)
{
if (req.Amount < 10000)
Console.WriteLine("{0} $$ Loan approved for {1} - Approved by {2}",
req.Amount, req.Customer, this.Name);
else
this.TrySuccessor(req);
}
public IRequestHandler Successor { get; set; }
}
//Main driver
class Program
{
static void Main(string[] args)
{
//Customers
var request1 = new LoanRequest() { Amount = 800, Customer = "Jimmy"};
var request2 = new LoanRequest() { Amount = 5000, Customer = "Ben"};
var request3 = new LoanRequest() {Amount = 200000, Customer = "Harry"};
//Approvers, chained together
var manager = new Manager() {Name = "Tom, Manager"};
var cashier = new Cashier(){ Name = "Job, Cachier", Successor = manager};
//All customers request cashier first to approve
cashier.HandleRequest(request1);
cashier.HandleRequest(request2);
cashier.HandleRequest(request3);
Console.ReadLine();
}
}
}
And this is what you’ll see upon execution.
So, you may observe that Loan Requests from different customers are passed to the cashier in the above example, and the cashier in his approve method passes the request to his successor (i.e, the manager) if the amount is higher than what he can approve. The implementation is pretty minimal, as you can see.
We actually have an Abstract request handler implementation IReqeustHandler and two concrete request handlers, Cashier and Manager. Each request handler may hold a reference to the successor. You may see that we are setting the Successor of Cashier as Manager, so if the amount requested his beyond a limit, the cashier may pass it to the manager for his approval.
Dynamically Injecting Approvers
Now, let us take a step back, and think how to implement this in such a way that the approval pipeline is extensible? As of now, our pipeline has two approvers, cashier and manager, and the manager can approve loans up to 10,000. Tomorrow, the Bank may decide that the General Manager can approve loans above 10,000 – and what you are going to do? Make the changes, Recompile the entire application, move it to QA, initiate a full recursion testing, and deploying everything to production? You may leverage a bit of extensibility here, and let us have a look at leveraging MEF (Managed Extensibility Framework) for the same.
I recommend you to go through my introductory posts on MEF if you are not familiar with MEF concepts.
Let us go for a generic implementation, to load and compose the handlers leveraging MEF. Let us generalize the above implementation a bit, and introduce few more general purpose contracts and classes.
IRequest – This contract should be implemented by all requests.
IRequestHandler – Same as earlier. Abstract request handler implementation
ExportHandlerAttribute – A custom attribute to export MEF parts
IRequestHandlerMetadata – Used internally for storing the successor information as a type
RequestHandlerGateway – Does the composition, and passes the request to successors in a chained fashion.
To the code
//Abstract Request
public interface IRequest { }
//Abstract Request Handler
public interface IRequestHandler
{
bool HandleRequest(IRequest req);
IRequestHandler Successor { get; set; }
}
//A custom MEF Export attribute
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ExportHandlerAttribute : ExportAttribute
{
public Type SuccessorOf { get; set; }
public ExportHandlerAttribute()
: base(typeof(IRequestHandler))
{
}
public ExportHandlerAttribute(Type successorOf)
: base(typeof(IRequestHandler))
{
this.SuccessorOf = successorOf;
}
}
//The metadata to tie a handler to next successor
public interface IRequestHandlerMetadata
{
Type SuccessorOf { get; }
}
//A gateway which stiches together the handlers, to accept a request to chain through the handlers
//Note that this does the composition using MEF
public class RequestHandlerGateway
{
[ImportMany(typeof(IRequestHandler))]
public IEnumerable<Lazy<IRequestHandler,IRequestHandlerMetadata>> Handlers { get; set; }
private IRequestHandler first = null;
public RequestHandlerGateway()
{
ComposeHandlers();
//Let us find and keep the first handler
//i.e, the handler which is not a sucessor of any other handlers
first = Handlers.First
(handler => handler.Metadata.SuccessorOf == null).Value;
}
//Compose the handlers
void ComposeHandlers()
{
//A catalog that can aggregate other catalogs
var aggrCatalog = new AggregateCatalog();
//An assembly catalog to load information about part from this assembly
var asmCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
aggrCatalog.Catalogs.Add(asmCatalog);
//Create a container
var container = new CompositionContainer(aggrCatalog);
//Composing the parts
container.ComposeParts(this);
}
//Try to handle the request, pass to successor if required
bool TryHandle(IRequestHandler handler, IRequest req)
{
var s =
Handlers.FirstOrDefault(
h => h.Metadata.SuccessorOf == handler.GetType());
if (handler.HandleRequest(req))
return true;
else if (s != null)
{
handler.Successor = s.Value;
return TryHandle(handler.Successor, req);
}
else
return false;
}
//Main gateway method for invoking the same from the driver
public bool HandleRequest(IRequest request)
{
return TryHandle(first,request);
}
}
Cool. So we have the basic stuff there, keep that handy. Now, to have a Chain Of responsibility implementation, you can simply create the concrete parts and export the same. We’ve the following concrete parts.
LoanRequest – A concrete request
Cashier, Manager, and GeneralManager – Concrete request handlers
You may note that now we can chain the handlers using the Meta data. For example, when you export the manager, you can easily specify that Manager is the successor of Cashier, to approve the request. Similarly, you can specify General Manager as the successor of the Manager. The advantage is, you can simply deploy these components in a loosely coupled manager, and pick them up using the DirectoryCatalog of MEF during re composition.
//Concrete Request
public class LoanRequest : IRequest
{
public string Customer { get; set; }
public decimal Amount { get; set; }
}
//Concrete Request Handler - Cachier
//Cachier can approve requests upto 1000$$
[ExportHandler]
public class Cashier : IRequestHandler
{
public bool HandleRequest(IRequest r)
{
var req = (LoanRequest)r;
if (req.Amount < 1000)
{
Console.WriteLine("{0} $$ Loan approved for {1} - Approved by {2}",
req.Amount, req.Customer, this.GetType().Name);
return true;
}
return false;
}
public IRequestHandler Successor { get; set; }
}
//Concrete Request Handler - Manager
//Manager can approve requests upto 10000$
[ExportHandler(SuccessorOf = typeof(Cashier))]
public class Manager : IRequestHandler
{
public bool HandleRequest(IRequest r)
{
var req = (LoanRequest)r;
if (req.Amount < 10000)
{
Console.WriteLine("{0} $$ Loan approved for {1} - Approved by {2}",
req.Amount, req.Customer, this.GetType().Name);
return true;
}
return false;
}
public IRequestHandler Successor { get; set; }
}
//Concrete Request Handler - Manager
//Manager can approve requests upto 10000$
[ExportHandler(SuccessorOf = typeof(Manager))]
public class GeneralManager : IRequestHandler
{
public bool HandleRequest(IRequest r)
{
var req = (LoanRequest)r;
if (req.Amount < 100000)
{
Console.WriteLine("{0} $$ Loan approved for {1} - Approved by {2}",
req.Amount, req.Customer, this.GetType().Name);
return true;
}
return false;
}
public IRequestHandler Successor { get; set; }
}
//Main driver
class Program
{
static void Main(string[] args)
{
//Customers
Console.WriteLine("Enter Loan Amount:");
var amount = decimal.Parse(Console.ReadLine());
var req = new LoanRequest() {Amount = amount, Customer = "Ben"};
var gateway = new RequestHandlerGateway();
if (!gateway.HandleRequest(req))
Console.WriteLine("Oops, too high. Rejected");
Console.ReadLine();
}
}
And this is what you’ll get. You can see that the request gets dispatched to the correct handler.
I was very skeptical about CQRS (Command Query Responsibility Segregation) some time back, how ever after working on a CQRS implementation for the past few months for a customer in the telecom domain, I see better light. For some reason, there is a wide spread perception that CQRS is only for complex domains, how ever I think any true business system can benefit from CQRS principles. Here are few quick thoughts, mostly rants.
What is CQRS?
The basic idea of CQRS is pretty simple, this is from the CQRS summary post by Greg Young
Starting with CQRS, CQRS is simply the creation of two objects where there was previously only one. The separation occurs based upon whether the methods are a command or a query (the same definition that is used by Meyer in Command and Query Separation, a command is any method that mutates state and a query is any method that returns a value).
When most people talk about CQRS they are really speaking about applying the CQRS pattern to the object that represents the service boundary of the application.
As simple as that. I suggest you to read/bookmark the below posts.
So, most of the discussion happening these days is about the application possibilities and implementation details around CQRS, and these are just few random thoughts around the same, and these are not any pointers for anyone.
For a moment, let us forget what exactly is CQRS, let us see how your system or business normally works. The users or stake holders or external system interact with your system in two ways – basically they’ll ask the system to do something (commands), and they also need to view/visualize the state of the system in different ways (queries). In most businesses, the system will be queried not just for the current state, but also for historical changes – i.e, you need to track the history of changes (as in an audit log) and need special logic to capture intelligence about events happened in the past. Say, to answer like "how many users are removing product x from their cart after adding product y".
You could argue any system that is just CRUD is a database, and yes we can put any decoration on top of it to build some editing features. But any meaningful Business Context involves capturing intent from user, to validate the intent at times, handle it, and provide some meaningful read models to query.
So, I think CQRS allows modeling the domain in a more natural way. You can pick commands directly from the use cases (if well written), and you can focus on what the domain does or what the domain should do when a state change happens, and use this information to construct how different stake holders view the system. In our scenario, we had multiple dimensions/read model snapshots.
Do I need CQRS?
It is all about the ROI, isn't it? Theoretically, you could argue any BC that models a set of business scenarios can be benefited leveraging the CQRS principles, because that means your system will be able to answer a lot of business related questions implicitly. Do you need that or not? That's a business call.
Here is my top three reasons based on my limited exposure towards CQRS based models.
The users or stake holders or external system interact with your system in two ways and if you are specifically focused on capturing the user intent– basically in any system, they’ll ask the system to do something (commands), and they also need to view/visualize the state of the system in different ways (queries).
In case your system will be queried not just for the current state, but also for historical changes – i.e, you need to track the history of changes (as in an audit log in a stereotypical system) and need special logic to capture intelligence about events happened in the past. Say, as I mentioned, to answer like "how many users are removing product x from their cart after adding product y".
Your management/customer thinks it'll add value to them on the long run, i.e, the system will help them have an edge over the competition. Oh yea, you have to sell this to them.
There is going to be a spike in the CapEx, may be because building Task Based/Inductive UIs are more costly than spread sheet like grids/CRUD focused forms where the user has to bring up the entire form to change the status from open to closed or what ever. Other than that, I think the cost is totally dependent on the design and related details, and the way you implement CQRS along with other DDD patterns.
CQRS and Event Sourcing
CQRS can be a simple separation of commands and queries, but I think the real value is if you tie CQRS with Event sourcing - it allows you to capture the system as how it came to the current state, rather than what it is right now. So, you are adding a new dimension to the system, i.e, the time. And you can take snapshots of the system at different times, and then compare it, that is valuable business intelligence. I think we don't need to see the read model as just a static snapshot of the system at a given time - it can even be derived from the state of the system at two different times.
And you can build read models based on multiple dimensions - to answer questions related to the system's behavior as well. For example, a stereotypical system can't answer even simple questions like "how many users are removing product x from their cart after adding product y" with out explicit design to capture the scenario. In a CQRS system this is implicit.
You can plugin a new dimension that constructs a read model to answer the query. About the cost - I think the key is in bringing in the mindset and selling this idea to the stake holders - even if the initial investment is a bit high, that will significantly improve their ROI and place them ahead of the competition.
How ever, the problem is, the world may be too corrupted with people like us, who were trying hard to persist a single state snapshot of the system in a mismatching ER model and then trying to keep it up to date and worrying about all related issues, to further mess it up with audit logs and all other mining crap when business starts asking critical questions.
Based on the recent experience, I’ve got a feeling that REST and CQRS goes well together, and there is a bit to explore there. To start with, they way we implemented Commands in one of the recent system is over a REST API, where the URL scheme represents the commands.
Say, for example, if the user need to close and issue, the end point will be like http://server/issue/close - The end points are used to identify the command handler and pass it to the same. Command handlers are registered in a container, in our case we used MEF to export the command handlers, something like
Message is essentially a key value store as in a dictionary, and this allows us to cope up with versioning. We had a REST based Querying API too. And we were federating the commands to the results/DTOs as in Hypermedia
i.e, here is an example
[ExportCommandHandler("Issue","Close")]
public void CloseIssueCommandHandler(int id) {..}
I couldn't figure out a defined way for the Task Based UI to find out possible commands based on the current state. Probably this is more or less an implementation related aspect and all of us are free to choose. We could do the validation of the command after it is issued, but in some scenarios, it is better to prevent the user from issuing the command in first place.
I.e, let us consider a DTO,
<issue>
<id>1</id>
<description>A bug is trying to hug me</description>
<otherfields/>
<link rel="rc:closeissue" url="/issue/close/1">
</issue>
Now, when a user closed an issue, a CloseIssuecommand has gone in and if the operation succeeds, an IssueClosed event has been logged to our event store - Now, as the issue is already closed, you don't need to (or you should not) provide the CloseIssue action to another user again, because the Issue is already closed by some one.
So, in our scenario, we had some decorators on top of the Query builder to evaluate the current state, so that only the required commands are federated to a returned result. So, the Task Based UI can be more intelligent (and the TB UI is anyway issuing commands based on the DTO information it has).