PAGES

10

May 12

Roll your own Twitter Feed with Backbone.js




Backbone.js is a JavaScript framework that manages complexity on the client while enabling the creation of rich HTML5 applications in a MVC-style fashion. For the more tech-savvy:

Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.

Created by THE Jeremy Ashkenas of Document Cloud (creator of CoffeeScript – more on that later).

Setting the stage

In this post we’re going to make our own sample Backbone.js app that utilizes Twitter’s search API to scrape tweets and display them with the underscore templating engine and twitter bootstrap themes with a subtle patterns background. Node.js will deliver our static html file while Dropbox will host our JavaScript files (providing us with a make-shift CDN “Content Delivery Network”). Our app will be hosted on www.cloudfoundry.com with www.c9.io as our staging server while using git as our source control.

Final Result

Usually with tutorials I scroll to the bottom to see if the example is even worth making, then I decide to read the post if it is. So let me save you the trouble of scrolling and just show the final result here.

Setting up our server

For those of you that don’t know node.js like me. It’s worth checking out and is compatible on all major operating systems. According to node’s site.

Node.js is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.


Some users of node are Microsoft, LinkedIn, eBay and Voxer.

For more info on getting started with node, express and npm (node package manager) check out this tutorial. For more info on what exactly node is, check out this link. There are also plenty of other great ebooks on Amazon.

If you’re coming from the Microsoft paradigm think of express as your ASP.NET MVC 3 web app framework. For our example we are only distributing one html file (since our app is a simple single-page app) that needs no server interaction. The code should be very straightforward.

// Configuration

app.configure(function(){

  // disable layout
  app.set("view options", {layout: false});

  // make a custom html template
  app.register('.html', {
    compile: function(str, options){
      return function(locals){
        return str;
      };
    }
  });
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

app.get('/', function(req, res){
  res.render("index.html");
});

app.listen(3000, function(){
  console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});

The Html

Main highlights here are as follows:


Here we see by appending classes to div’s twitter bootstrap will easily create a persistent header with optional header text.

<header>
    <div class="navbar navbar-fixed-top">
      <div class="navbar-inner">
        <div class="container-fluid">
          <a class="brand" href="#">Clarity Twitter Feed</a>
          <div class="nav-collapse collapse">
          </div>
        </div>
      </div>
    </div>
</header>

Here in our tweet template we iterate through each tweet and display the respective content in

tags and append the image url onto the “src” attribute of an tag.

<script type="text/template" id="tweettemplate">

    <!-- nav -->
      <nav>
        <button class="refresh btn btn-success btn-large">
              <i class="icon-white icon-refresh"></i>Refresh
        </button>
        <button class="reverse btn btn-warning btn-large">
              <i class="icon-white icon-resize-vertical"></i>Reverse
        </button>
      </nav>
    <!-- /nav -->

    <!-- List of Tweets -->
        <section id="content">
          <ul id="tweetList">

          <% _.each(tweets, function(tweet) { %>

          <li class="tweet">
            <span>

                <div class="head">
                    <img class="pic" src="<%= tweet.profile_image_url %>" />
                    <p class="userId"><%= "@" + tweet.from_user %></p>
                 </div>

                 <div class="tail">
                    <p><%= tweet.text %></p>
                    <p class="created"><%= tweet.created_at %></p>
                 </div>
                 <hr />
            </span>
           </li>  

          <% }); %>

          </ul>
        </section>
     <!-- /List of Tweets -->
  </script>

The CSS


This was a great exercise in learning more about CSS and some of the new CSS3 styles like dropshadow and border-radius. Going forward I’d like to use more style inheritance and eventually use LESS. (Actually, if you convert this CSS to LESS, it will look the exact same :) )


 body {
  background-image: url('http://dl.dropbox.com/u/10021156/NsLayout/img/white_tiles.png');
  padding-top: 60px;
  padding-bottom: 40px;
  margin: 0 auto;
}

#narrLogo {
  margin-left:34px;
  padding : 10px;
}

#message {
	position:absolute;
	margin-left:152px;
	margin-top:24px;
	color: white;
}

nav {
	width:85%;
	margin: 10px auto;
	padding: 10px;
	background-color: rgba(19,101,53,0.6);
	border-radius:10px;
	margin-bottom:47px;

}

#logo {
	width:50%;
	margin: 0px auto;
}

#tweetList {
	list-style: none;
}

.hero-unit {
	background-color:rgba(0,0,0,0.1);
	display:inline-block;
	padding:20px;

}

.reverse {
	float:right;

}

.container-fluid {
	margin-left: auto;
	margin-right:auto;
	width:600px;
}

.head {
	display:inline-block;
	padding:10px;
	border-radius:5px;
	background-color:rgba(0,0,0,0.1);
	opacity:0.9;

}

i {
	background-position : -435px -119px !important;
}

img.pic {
	box-shadow: 6px 8px 8px #888;
	height:60px;
	width:60px;
}

.tail {
	padding:2px;
}

.userId {
	display: inline-block;
}

.created {
	font-size:14px !important;
	font-weight:bold !important;
	margin-top:-13px;
	background:white;
	display: inline-block;
	border-radius:5px;
	padding: 0px 3px;
	margin-left: 14px;
	opacity:0.9;
}

.userId {
	margin-left:10px;
}

The Model

var Tweet = Backbone.Model.extend();

Well that was easy. We can define our Tweets field names and default values by passing in a defaults object into the extend() method of the Model class. But since this is JavaScript we can add properties on the fly and default values would not make sense for the properties in this example.

The View

On initialize the view will call fetch on our collection of tweets which will use the sync method to initiate an ajax call to Twitter’s API.
The resulting data will then be passed through the parse method, into the render method, and applied to the template. It’s best to look at the View while looking at the Collection code. (see below).

 TweetsView = Backbone.View.extend({
    initialize: function() {        

      _.bindAll(this, 'render');
      // create a collection
      this.collection = new Tweets;
           this.collection.on('reset', this.render);

      // Fetch the collection and call render() method
      var that = this;
      this.collection.fetch({
        success: function (s) {
            console.log("fetched", s);
            that.render();
        }
      });
    },

    el: $('#tweetContainer'),
    // Use an external template

    template: _.template($('#tweettemplate').html()),

    render: function() {
        // Fill the html with the template and the collection
        $(this.el).html(this.template({ tweets: this.collection.toJSON() }));
    },

    events : {
        'click .refresh' : 'refresh',
        'click .reverse' : 'reverse'
    },

    refresh : function() {

     this.collection.fetch();
    console.log('refresh', this.collection);
     this.render();

    },

    reverse : function() {

       this.collection.reverse();
       console.log(this.collection.reverse);
    }

});

var app = new TweetsView();
});

The Collection

Here reverse will override our comparator to display tweets in reverse order by way of the ternary operator provided to us in JavaScript.
Tweets = Backbone.Collection.extend(
    {
        model: Tweet,
        // Url to request when fetch() is called
        url: 'http://search.twitter.com/search.json?q=claritycon',
        initialize : function(){
            this.sort_order = 'desc';
        },
        parse: function(response) {

            //modify dates to be more readable
            $.each(response.results, function(i,val) {
                val.created_at = val.created_at.slice(0, val.created_at.length - 6);
              });

            return response.results;
        },
        // Overwrite the sync method to pass over the Same Origin Policy
        sync: function(method, model, options) {
            var that = this;
                var params = _.extend({
                    type: 'GET',
                    dataType: 'jsonp',
                    url: that.url,
                    processData: true
                }, options);

            return $.ajax(params);
        },
        comparator: function(activity) {
            console.log("this is comparing");
            var date = new Date(activity.get('created_at'));
            return this.sort_order == 'desc'
                 ? -date.getTime()
                 :  date.getTime()
        },
        reverse: function() {
            console.log("this is reversing");
            this.sort_order = this.sort_order == 'desc' ? 'asc' : 'desc';
            this.sort();
        }
    });

Refresh and Reverse

When refresh is clicked you can watch the ajax call in Chrome tools.

A note about Twitter’s APIs


The twitter API comes in 1 of 3 flavors. For our example we will use the search API which will allow us to retrieve tweets in jsonp (json with “padding”) and parse them on the client. It’s important to note that we are making a cross-domain request so we have to use jsonp to avoid the “same-origin policy” issue. One thing to also note, the search API only allows for 150 requests per hour per client and is limited in the amount of tweets that can be retrieved as well as historically how far back you can dig up tweets.

Git it


Probably the simplest and easiest commands you will use when deploying your site to a hosting provider like github, heroku, appharbor. Just remember these few simple commands and you will be able to upload any app anywhere.

  • git init //initializes the repo
  • git add . //adds all files in the current directory to the repo’s changeset
  • git commit -m “First Commit” //commits all the changes to the repo
  • git remote add github git@github.com:(username)/(reponame).git
  • git push github master

You can now import your github repo into www.c9.io and deploy it to cloud foundry.

Get the source here

0 comments , permalink


8

May 12

Contact Center Overflow queuing… Why you should never do this.



    I’m very excited to be onboard here at Clarity as the Product Manager for Clarity Connect. I am eager to share lots of the great stuff we’re working on here for improving this great product. I also want to begin to share my thoughts and experiences gained in my 10 years as a Contact Center Consultant. The first of which is my strong opinion that overflow queuing is one of the worst things you can do. Ever.

The Problem: Calls sitting in Queue Vs. Calls Answered in set amount of time

    Think about what you’re trying to accomplish: get a call answered. Now think about your caller, and what they are trying to do: Get some help regarding a specific topic. So for you, your goal may be to make sure all calls are answered by a warm body within X amount of time. However, If you route the call to an overflow queue that has agents who cannot actually assist the customer, you may be meeting your goal of getting the call answered by a live agent, but not meeting the customers goal of getting to talk ot someone who can help them solve their issue. As a customer I will always argue that I would rather hold a little longer, and either be given an option to leave a message for a callback, leave a callback placeholder in queue, or stay on the line, rather than being routed to someone who can’t help me out. The more times I have to repeat myself to explain who I am and why I am calling…. the less satisfied I am.

    The second problem with this is that it plain muddies up the reports. Your queue reports no longer show clean easy to read numbers of calls presented, answered and abandoned to this queue. You now have to spend a bunch of time or money trying to figure out how many were initially presented here, but then de-queued and re-queued elsewhere.

The Solution:  Keep it simple, Either an Agent is skilled to handle the call type or they are not.

    If the agent is skilled to handle these calls, and you want them to be “Overflow” Agents, then simply use Skills Based Routing with levels. All the Agents you wish to primarily handle these calls, skill at the highest level. All The Agents you wish to be in the secondary group get scored at a lower level and so on. you can create multiple levels of “Overflow” this way, while still ensuring that callers only get their calls answered by agents who can solve their issues, and your reports stay clean, because calls are only presented to a single queue. (you can still escalate to a level two type of scenario, or subject matter expert queue… that is different than overlfow)

Here is an example to try to illustrate the point.

    Caller chooses Technical Support from the IVR tree, gets routed to the Queue for Technical Support. After 65 seconds in Queue, the system de-queues the call and re-queues it to Customer Service to try to get it answered within 90 seconds. The CS Agent answers the call, but can’t actually help the customer. Caller is Mad, CS Agent is frustrated by having to chase down someone who can help the caller and not perform the duties they can perform, instead they have become an operator, or a manual call distribution service. reports are messy, etc…

The Better Option:

    Caller chooses Technical Support from the IVR Tree and gets routed to the Technical Support Queue. The system looks for the Primary group of agents (those with the highest skill level) if any are available it will route the call to the longest available fo those highest skilled agents, if they are all busy, overflow by skill routing automatically kicks in and the system checks the next highest skilled group of agents, and so on. If at any point any of the agents who are skilled (high or low) to answer the call becomes available, the call is instantly routed to that agent. This also shortens the average hold times and handle times, etc, because the call doesn’t have to wait 65 seconds or whatever is configured in the system before it brings in the other levels of agents to get the call answered, and not just answered, but answered by someone who can help the caller.

    This results in shorter times within the contact center, better overall performance of many factors within the contact center, as well as happier agents and customers.

This method has repeatedly proven to:

  • clean up reports
  •  lower average speed of answers
  •  raise customer and agent satisfaction scores.

    In 2011 I did this for three different contact centers improving all of these items, the most significant of which had average hold times in queue across their system that were in the 12 minute range with 5 different levels of overflow routing. After switching to this type of skills based overflow routing (as well as a complete redesign of their IVR eliminating all manual overflows) their average hold time went down to just under 2 minutes. This also increases agent effectiveness, and the number of calls they are able to handle each day.

   If you’re looking for a Contact Center Solution for Microsoft Lync, please contact us to see how Clarity Connect can solve these and many more problems for you.

Please feel free to comment below or contact me if you wish to discuss this.

0 comments , permalink


28

Apr 12

Windows 8 from the Trenches



Last week Clarity was invited to the Windows 8 Developer Launch event in here in Chicago. Matt Hidinger and I were asked by some good friends at Microsoft to give our 2-cents on why we’re excited about Window 8. It was a packed event, and we had a great time. Below are some pictures, slides and a short recap on our talk. Pictures courtesy of Bob Laskey

Win8 : A Business Perspective

Here at Clarity we’re excited about Win8 for a number of reasons. One of the wins we see from a business perspective is reusability in three main areas: Design, Code, and Skillset.

Design – We can now share design assets and create a consistent brand experience across Microsoft’s three major screens: Xbox, Windows Phone, and now Windows 8.

Code – We primarily use C# and XAML to build our Windows Phone apps. Xbox, and Windows 8 also give us a framework to write C# and XAML. While the code isn’t necessarily copy & paste, there is a ton of overlap between the platforms.

Skillset – This is sort of a nice side-effect of having similar coding platforms. We are now sharing talent across our dev projects. In other words, our mobile guys are building Win8 apps and our XBOX guys are able to make the transition to Win8 or Win Phone just as easily.

Win8 : A Design Perspective

I’ve been building and designing software for a long time. And as a ‘design guy’ I tend to focus primarily on the UX aspects of software. With Windows 8, UX and aesthetics have finally been promoted to a first class citizen. This is great news for both designers and developers. This is especially exciting from a development perspective because it makes good design a hellava lot more accessible to the non-designer.

Metro makes Design More Accessible. . I like to think of Metro as a ‘developers kind of design’. It gets to the point, and promotes functionality over flash. Its about solving problems, visually, which is something we can all get on board with.

That last statement might seem a little broad. Specifically, the Windows 8 platform makes a handful of tedious design scenarios very easy for developers :

  • Touch First Controls – MS has finessed the crap out of these touch controls. They are accurate, and have a ton of user research driving their functionality. This is something that takes a lot of precision and therefore time to nail. Now you get it for ‘free’.
  • Animation – I’ve spend a good portion of my career figuring out the ‘perfect’ easing functions and timings to create snappy elegant motion in applications. MS has spent a bunch of time making the animation framework super easy to use for everyone. Its really good. Use it.
  • Built-in Styles – Margins, spacing, alignment, font-sizes, type-casing, font-weight. These are things that make most developers cringe. Well guess what, MS has been awesome enough to provide you with templates that have all of the base styling built-it so you don’t need to fret about those teeny-tiny pixels.
  • Win8 : A Development Perspective

    Our own Matt Hindinger did an awesome job talking about the great new development opportunities that come with the Win8 Metro platform. I’ll make a feeble attempt to recap the highlights of his portion of the talk.

    In Metro you have a choice to use 3 different development platforms : HTML5/Javascript, XAML/C++, XAML / C#. And the question we get asked the most is ‘when do I use what?‘. This is the when & where breakdown that we’ve come up with:

    • C++ XAML / DirectX – We think this platform is best used when you have a need for performance and precision. C++ and DirectX give you full control of every pixel on the screen and its super fast.
    • C# / XAML – This is our platform of choice. It offers a very reliable strongly typed coding environment that couples speed of development and a robust control set. If you come from a .net background, this is the one for you.
    • HTML5 / Javascript – We think this platform offers great flexibility and an awesome set of tools for loose and fast prototyping. If you are coming from a web background you will be pleasantly surprised at the modern CSS, js support. We’ve had really good success with this framework so far.

    Our Slides

    Below is our slides from the event. Check em’ out and share them with your friends. We had a lot of fun embracing the ‘trenches’ theme .



    If you have any questions or thoughts you’d like to share with us don’t hesitate to hit us up on twitter.

    Best,
    Erik Klimczak | e = eklimczak@claritycon.com | t = eklimcz

    0 comments , permalink


25

Apr 12

Bare Minimum JS – Part 2 – Scoping



Scoping Things Out

In our last post, we talked about ways to create objects in order to keep our code tidy and organized.  The next concept we’re going to explore is also a way to keep our code tidy and out of the way of each other; Closures and Scoping.

The Old and Busted way

function highlightMenu() {
    // Find my the current menu item and highlight it...
};

function loadWizzyMathinger() {
    // Load the almighty Wizzy Mathinger
};

function handleItemClick(evt) {

};

// On Document Ready
$(function() {
    
    highlightMenu();
    loadWizzyMathinger();

});

// Maybe later in the page, autoload = you do something like this
<a href="#" onclick"handleItemClick">Some Item</a>

view raw badScoping.js This Gist brought to you by GitHub.

Here’s a common story.  You start out with just a couple pages on your website.  You don’t see the harm in just throwing your javascript directly in a script block, maybe even (<gasp>) directly calling javascript from html event attributes.  But, quickly, you’ve added a bunch of new objects to the global scope and if your application ever gets much more complicated your going to end up having a hard time finding what functions are firing and debugging code paths because of the lack of structure.

First off, shame on you for putting javascript in an HTML attribute.  Somebody has to make a value judgement at some point, and for me, it’s javascript event handlers on HTML tags.  Sorry, had to be said.

The New Hotness

Here is a much more stable way to encapsulate your page logic using a “closure” technique.

// pages.Page1.js
// I like to include the file name at the top in case we ever concatenate our scripts and need to find this file to debug.

// Wrap each block of code in a self executing function.
// At the bottom, we pass in these objects to this function and immediately execute it.
(function($, window, document) {
    "use strict";
    // Optionally, a single string "use strict" will force strict mode and help you catch common javascript errors before they get into the wild.
    
    // Pass in jQuery and the window object to protect from other people messing with their values.
    // Also, if you are referencing window or document alot, minimizers can optimize this file into a smaller size.
    
    var page1 = {
        
        ready: function() {
            highlightMenu();
            loadWizzyMathinger();
            setupEvents();
        },
        
        highlightMenu: function() {
            // Highlight the current menu item.
        },
        
        loadWizzyMathinger: function() {
            // Load the mystical Wizzy Mathinger...
        },
        
        setupEvents: function() {
            
            // workaround for javascript's crazy scoping of "this"
            var self = this;
            
            // A better way of handling any time .someItem is clicked on the page.
            $(document).delegate("a.someItem", "click", function(evt) {
                self._handleItemClick(evt);
            });
        },
        
        // By convention, "private" methods usually are preceded by an underscore. It also helps to keep them out of the way when ordered (in intellisense, for example)
        _handleItemClick: function(evt) {
            // Handle our item click.
        }
    };
    
    // On document ready hook.
    $(page1.ready);
    
}(jQuery, window, document));

Whoa.  Settle down.  I know, it’s a little bit more complicated.  Let’s start with the toughest thing on the page; the self executing function we wrapped everything in.

Breaking it Down

All we are doing is creating a function and immediately executing it.  The main reason we would want to wrap our code like this is to keep it out of the global scope and therefore more modular and tidy.  After running this function, we’ve created a new page1 object and subscribed to the document.ready event with the page1.readyhandler all without any artifacts in the global scope.  Plus, we get a nice way to represent the logic on our page in an object oriented way.

The “use strict” is kind of esoteric, but it brings some helpful checks for some of the quirks of javascript.  I won’t go too much into detail here, but check out John Resig’s great article on strict mode.

Next, we use the handy dandy object initialization syntax we talked about in our last post to group together the functionality for page1.  Also, in the setupEvents() method I show an example of how to subscribe to events on elements in a more isolated way than putting functions in html attributes.

Next Time

Classes and scoping can really start to make your Javascript heavy projects much easier to handle.  But, it gets even better when we start to introduce another concept called the Module Export pattern.  Stay tuned, it’s gonna be good for you, I promise.

Now PlayingDashboard Confessional – Screaming Infidelities

 

0 comments , permalink


18

Apr 12

Bare Minimum JS – Part 1 – Getting Classy



The Bare Minimum You Need To Know About Javascript

Part 1 -Getting Classy

These days, it seems JavaScript is taking over the whole earth. Chances are, if you’re starting a new project it’s probably going to involve some JavaScript.

JAVASCRIPT ALL THE THINGS!!!

A wise man once told me, “JavaScript is for hackers” and, that is both a blessing and a burden for the common developers relationship with the language. A common developer coming from a strict OOP language like C# or Java is going to be turned off by some of the functional concepts and the lack of an easy way to keep things modular and tidy.

With that in mind, let’s dive in by introducing one of the basics that will help keep your code organized.

Get Object Oriented

JavaScript has two common ways to create an object. First, let’s take a look at the quick and dirty way to make an object.

// The quick and dirty way
var baby1 = {
  name: "cutesy",
  sex: "F",
  speak: function() {
    return "gaga"; // As in Lady
  }
};

// Functionally equivalent to this...
var baby1 = {}; // Or, even new Object();
baby1.name = "cutesy";
baby1["sex"] = "F"; // Notice what I did there?
baby1.speak = function() {
    return "gaga"; // Still, as in Lady.
};
view raw quickClass.js This Gist brought to you by GitHub.

That is the easiest way to just group a bunch of variables into a class. It’s quick and easy but has some downsides to keep an eye out for. If you need to make a lot of these you’re going to have to type that out a lot which could lead to fat-fingering it some place. There’s also the fact that the speak() function we created is an instance variable on each object, which means it will take up more memory than if we defined it in the more classical prototype fashion that would share the function across objects.

// The classical prototype way
/* Define a constructor */
function Baby(name, sex, says) {
  
  // Set some variables on the object
  this.name = name;
  this.sex = sex;
  this.says = says;
}

/* Define the baby.speak() method */
Baby.prototype.speak = function() {
  return this.says;
};

/* This is how we instantiate our Baby class */
var baby2 = new Baby("wootsy", "M", "googoo"); // As in Dolls

The classical prototype way is a little more verbose, but it comes with the benefit that we now have a way to really pump out some Baby objects if we needed to. Notice the way we use this in the constructor to make instance variables on the object (more on the magic of this in another post.

My rule of thumb is to use the quick and dirty way when I’m making a “one off” object that is just temporary and won’t have many instantiations.

I try to be strict about using the classical approach when I’m creating something that will have more than one instance of itself in my app.

Next time, we’ll talk about closures and some of the ways we can keep our newly created objects from banging into each other in the global scope.

Now PlayingThe American Dollar – Anything You Synthesize

_

1 comment , permalink


17

Feb 12

WF4 – Pretty Flowcharts and Visualizing Business Process



When to Flow

During the elaboration phase of a recent project I could feel a disconnect between what the developers where saying and project management wanted. Developers were able to describe a set of high level processes to each other and project management struggled to understand how the system all fit together. In a high level sense the project is an order fulfillment system with a small application used for configuration (not that important in the grand scheme of things). The system will have a series of triggers that aggregate data from various sources to determine if an order can be placed. During these elaboration meetings I kept thinking about how this system fit well into a State Machine, but I didn’t want to go the route of a coded State Machine. I had heard very little about WF4 (Windows Workflow Foundations 4), but it did have the appeal that it could present a visual representation of the main process for order fulfillment. Immediately I began thinking about how easy it would be to convey to new developers here is the process for our system and also how this visual display could be also double up and help project management understand what exactly we are thinking of as developers. I’ll admit a fancy series of Activity diagrams or flowcharts might do the same, but I like the idea that this diagram really represents what the underlying code is intending to execute. Much less smoke and mirrors…

Workflow Overview

To better understand the usefulness of WF4 it is best to get a grounding in what a Workflow is and the related technologies. A workflow is a series of interrelated steps that defines a process that can be thought of as the work of a single entity or a group. In this sense a workflow can be the representation of work (real or abstract) that is achieved by its execution. Businesses have used workflow process modeling to understand system usage of resources including how those resources transition in and out of system. In these transition locations there will always be potential for inefficiencies and evaluation of the system in this manner can provide talking points on where and how to implement improvements.

Simple Order Process
Consider the Simple Order Process workflow shown to the right. It has a discrete amount of steps: Receive Order, Process Order, Charge Customer, and Ship Order. Each time this workflow is run it will flow through these steps and that should cause a few questions to come up. Is it really necessary to execute these steps? What happens if the received order is empty? Should the order ship if charging the customer fails? Is there any feedback that should be transmitted to a customer when an order is shipped or throughout this workflow process? While the previous questions are all fairly simple it does bring to light possible issues in the system by being able to visualize it and understand the logical series of steps.

 

Workflow Engine and Workflow Patterns

WF4 is Workflow Engine that employs Workflow Patterns. A Workflow Engine is a piece of software that manages and executes modeled processes or Workflows. A Workflow Engine reacts to events in the system, such as receiving an order in the example above, and processes related information, the received order (hidden under the covers of course), producing a result that can be used in subsequent steps if system constraints have been met. Workflow Patterns help define the Workflow into recognizable actions such as do..while, foreach, parallel action, sequences (in the case of the Simple Order Process), flowcharts, and state machines to name just a few. The Simple Order Process example is just a sequence containing 4 activities and it lacks a great deal of functionality because it is setup to follow that flow each and every time. This can be addressed in a number of ways, but I’m most interested in WF4′s State Machine.

Enter the State Machine

State Machines provide the possibility of branching logic for a workflow and help address the previous concerns about the robustness of the Simple Order Process. By translating the previous activities in the previous sequence into states and creating triggers or constraints it will be possible to create the State Machine incarnation of the Simple Order Process. But what exactly is a State Machine in WF4?

Simple Order Process State Machine
Shown above is a simple rendition of what the previous Simple Order Process might look like as a State Machine. From a quick glance it is possible to see the intended progression of states in the system. There is still much that is hidden at this level, but it gives talking points to the business side such as when the system is in the “Charge Customer” state that there will be one of two transitions to either “Shipping the Order” or “Canceling the Order”. It is possible to drive down into individual states to view what exactly is going on, but from a high level view that could be argued away that states would be named in such a way that any user could immediately guess.

State Machine Basics in WF4

State Machines existed in WF3 (previous version), but when WF4 emerged State Machines did not exist “officially” until .NET Platform Update 1. For more details on the progression of WF’s State Machine take a look at The Activity Designer Blog on MSDN. To think in terms of State Machines it is best to understand it as a collection of States that have Transitions between states and there is always a Initial State and Final State. The simple difference between general States and the Initial/Final States are that can be transitioned To and From where as Initial/Final support only To and From respectively. Transitions describe how the system moves between states. It is easy to relate them to events that occur and the system reacts to them triggering a state change.

State
In WF4 each State is made up of Activities, any class that implements System.Activities.Activity, that control what occurs in the state upon entry and prior to exit. In the Change Customers state above it is possible to see that upon entry into this state a ChargeCustomer activity will be executed and upon exit a sequence of activities will be executed (SendEmail => UpdateCustomer). This is a typical view of a state from the designer and it should be noted that any control flow activities can be embedded into the entry and exit portions of a state. One other piece to notice is that exit state will list what state transitions are available and the triggers that cause the transition.

Transitions between states are the results of Trigger Activities and come in a few flavors: null, shared, and everything else. Trigger activities execute and the result is typically evaluated to determine the next logical state. In the case of the Simple Order Process after Charge Customer there might be an Order Prep finished event that causes a trigger to evaluate and either transition to Order Ship or Cancel Order state.

But that is just a small piece of Workflow as it is neglecting more complex transitions/triggers, Tracking Participants, how to save/resume workflows, hosting a workflow in a WCF service, and many other features.

Where’s the Beef (Code)?

The idea of using WF4 to model the system design and move forward with it would have been too costly for the team to take on for a number of reasons:

  • Nobody at the time was an expert on WF4 or any previous incarnation
  • Shorter time frame did not leave much room to dream big in the design department
  • WF4/StateMachine may not have been the ideal choice
  • The business group may still have been confused after seeing the process visually

Given the time I would have spent a few days mocking up the Order Process that the system was intending to use and provide it as a proof of concept to the group. I think once the design could transition past the state modeling stage breaking up the code into the functional units of state work and transitions would have been fairly straightforward. I do plan on writing up a Simple Order Processor as a post-project proof of concept mostly to satiate that original desire to create a State Machine to handle order processing and better understand how WF4 might fit into my consulting bag of tricks.

Further Reading

3 comments , permalink


6

Feb 12

A Web Recipe: Thoughts on making this better



This is the final post in the series described here.

I thought I’d wrap up by touching on a few thoughts to improve the solution and take it further, some of which I did implement in the code.

Simple Usability Enhancements

As it stands, users have to enter a date in a proper format. Why not just let them choose. So I added a simple update to use the jquery UI date picker on the review dialog.  Also, the grid default sort was never set.  Using the aaSorting initialization parameter, you can specify which column should have the default sort in a grid.  I added this to both grid instances.

Style

None of what I built had much style.  It really doesn’t look like it is part of a site for that matter as it was simply a POC without any real use cases.  The patterns have sort of an Admin feel which might not map to a great consumer Beer application.  That aside, here is where the MVC approach is nice.  Without touching server code, we (or better yet a designer) can improve the markup, add some CSS classes and define some style rules and quickly have us looking much better. 

Data Access Layer

I referred to use of my datacontext as a data access layer.  There is certainly a lot of room for opinion on approaches for better abstracting that away.  One approach would be to take all the domain classes like Beer and Brewery and move them to a Clarity.BeerApp.Data.Model assembly, leaving the context in the Data assembly.  My entities really don’t need to know anything about EF and can be separated.  Then I can build mock contexts and support better testing.  I may do this in the future and post an update.

Routing Improvments

Similar to the DataTables parameter binding improvements I suggested in the posts, there may be other ways to take better advantage of MVC features.  I didn’t explore this, but there may be some benefit to registering routes with the app to better handle some of the Review edits which would simplify the url creation.  Or maybe the Review views should have their own controller.  That is all open for debate.

In summary, this sample and set of posts was a starting point for me to look into combining Entity Framework 4.2, ASP.NET MVC 3 and the jquery DataTables into a web app.  I built off of some other’s ideas referenced in the initial post and hope this might help as a reference for some else learning about these technologies.

3 comments , permalink


3

Feb 12

A Web Recipe: Modal dialog and grid for child entities



This post is the forth in the series of posts described here.

So far we’ve put a data model and data access layer in place use EF Code First, and built out a snappy Index view that uses the jquery DataTables plugin to load our grid of beers.  The next thing to explore is working with this type of grid on a detail page and using a modal dialog experience to add and edit the items in the grid.  In this example, I want to list reviews for each beer.

I start by opening my scaffolded Details view.  I add a new table, the javascript, and the server side Action to load it basically just like we did in the previous post.

<fieldset>
    <legend>Reviews</legend>
    <table id="tblReviews">
        <thead>
            <tr>
                <th>
                    Action
                </th>
                <th>
                    Rating
                </th>
                <th>
                    Comments
                </th>
                <th>
                    Date
                </th>
                <th>
                    Reviewer
                </th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
    <span id="btnAddReview">Add New Review</span>
    <div id="ReviewDialog" title=""></div>
</fieldset>

function loadReviews() {
    $('#tblReviews').dataTable({
        "bServerSide": true,
        "bFilter": false,
        "bLengthChange": false, // don't show dropdown for #items per page
        "sAjaxSource": '@Url.Action("ReviewList")',
        "fnServerData": function (sSource, aoData, fnCallback) {
            aoData.push({ name: "beerID", value: '@Model.ID'});
            $.ajax({
                dataType: 'json',
                type: "POST",
                url: sSource,
                data: aoData,
                success: fnCallback,
                error: function (jqXHR, textStatus, errorThrown) { alert('Error getting reviews:' + errorThrown) }
            })
        },
        "bProcessing": false, // don't want to use the default progress indicator at this time
        "aoColumnDefs": [
                { "sName": "ID",
                    "aTargets": [0],
                    "fnRender": function (oObj) {
                        return '<span class=\"EditReviewLink\" data-reviewid=\"' +
                            oObj.aData["ID"] +
                            '\">Edit</span>';
                    }
                },
                { "sName": "Rating", "aTargets": [1], "mDataProp": "Rating" },
                { "sName": "Comments", "aTargets": [2], "mDataProp": "Comments" },
                { "sName": "Date", "aTargets": [3], "mDataProp": "Date",
                    "fnRender": function (oObj) {
                        return formatJsonDate(oObj.aData["Date"]);
                    }
                },
                { "sName": "Reviewer", "aTargets": [4], "mDataProp": "Reviewer" }
            ]
    });
}

You’ll notice that I’m using a helper javascript function I’ve defined to format the JSON dates returned.  Another new addition is that I’m adding to the parameters that passed to the Action because I now need to know which beer I’m talking about.  This was one of the flexible points I liked about DataTables.  I’m simpy using Razor syntax to output the ID of my beer from the model, and add it to the aoData object sent up to the server.  The magical binding of MVC maps the ID to my beerID parameter and the other parameters to my JqueryDataTablesRequestParameters parameter.  I’m not going to support filtering in this grid so in the server code all I need to do is get all the Reviews for this beer, sort them, and send them back as JSON.

Now we need to allow users to add reviews (I added the one above through the initializer for the data context).  First I add a new view partial view called AddEditReview, making it a strongly-typed partial view based on my Review model class.  I changed the model type to a new class I created called AddEditReviewModel that has a Review property and a Model property that lets me know explicitly whether we’re performing an Add or Edit mode when saving.  This is a common pattern where you use a model that is strongly typed “view model” and maps to your view.  I also get rid of the default submit buttons (because the dialog plugin will add the buttons) and change the BeginForm helper line to set the action to be empty (we won’t let it submit on its own) and the form id to ReviewForm.  I also change the editor field created for BeerID to be a hidden field.

@model Clarity.BeerApp.Web.Models.AddEditReviewModel

@using (Html.BeginForm("", "Beer", FormMethod.Post, new { id = "ReviewForm" }))
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Review</legend>

        @Html.HiddenFor(model => model.Review.ID)

        <div>
            @Html.LabelFor(model => model.Review.Date)
        </div>
        <div>
            @Html.EditorFor(model => model.Review.Date)
            @Html.ValidationMessageFor(model => model.Review.Date)
        </div>

        <div>
            @Html.LabelFor(model => model.Review.Reviewer)
        </div>
        <div>
            @Html.EditorFor(model => model.Review.Reviewer)
            @Html.ValidationMessageFor(model => model.Review.Reviewer)
        </div>

        <div>
            @Html.LabelFor(model => model.Review.Comments)
        </div>
        <div>
            @Html.EditorFor(model => model.Review.Comments)
            @Html.ValidationMessageFor(model => model.Review.Comments)
        </div>

        <div>
            @Html.LabelFor(model => model.Review.Rating)
        </div>
        <div>
            @Html.EditorFor(model => model.Review.Rating)
            @Html.ValidationMessageFor(model => model.Review.Rating)
        </div>

            @Html.HiddenFor(model => model.Review.BeerID)
            @Html.HiddenFor(model => model.Mode)

    </fieldset>
}

Back in the Details view I add a new “button” that will open the modal and I also stub out a div that will serve as the shell of the modal. 

<span id="btnAddReview">Add New Review</span>
<div id="ReviewDialog" title=""></div>

Then I write some javascript and server code based the ideas in this post to get my dialog going.  I need to link to the jquery-ui javascript and style files so I do that in my _Layout.cshtml file.  And I create a function to initialize my shell div as a dialog. 

function initializeReviewDialog() {
    $("#ReviewDialog").dialog({
        autoOpen: false, minWidth: 500, minHeight: 330, modal: true,
        buttons: {
            "Save": function () { saveReview() },
            Cancel: function () { $(this).dialog("close"); }
        }
    });
}

Then I create a function to attach a click handler to my add button that will take the dialog shell, clear it out, and turn it into a dialog using the jquery UI dialog plugin. I’m also using the submit and preventDefault functions to prevent the default submit acion of the form and instead call my saveReview function. 

function wireAddReviewLink() {
    $("#btnAddReview").click(function () {
        $("#ReviewDialog").html("").dialog("option", "title", "Add New Review")
            .load('@Url.Action("AddReview")/?beerID=' + '@Model.ID',
                function () {
                $("#ReviewDialog > form:first").submit(function (e) { e.preventDefault(); saveReview(); });
                $("#ReviewDialog").dialog("open"); });
    });
}

So as a result of the click, the funciton above will load the dialog with the result of a call to our AddReview action that partially renders the view.

public ActionResult AddReview(Guid beerID)
{
    return PartialView("AddEditReview", new AddEditReviewModel() { Review = new Review() { BeerID = beerID }, Mode = AddEditMode.Add });
}
?

The last thing I need is javascript to save the review and reload the Reviews table and the action that supports saving the review.

function saveReview() {
    $.validator.unobtrusive.parse("#ReviewDialog > form:first");
    var frm = $("#ReviewDialog > form:first");

    if (frm.valid()) {
        $.post('@Url.Action("SaveReview")',
                frm.serialize(),
                function (data) {
                    if (data.Success) {
                        $("#ReviewDialog").dialog("close");
                        reloadReviews();
                    }
                });
    }
}

function reloadReviews() {
    $('#tblReviews').dataTable().fnDraw(0);
}

[HttpPost]
public JsonResult SaveReview(AddEditReviewModel m)
{
    if (!ModelState.IsValid)
    {
        return Json(new { Success = false });
    }

    if (m.Mode == null)
    {
        // just a safety check - shouldn't really happen
        throw new Exception("Unsupported operation.");
    }

    if (m.Mode == AddEditMode.Add)
    {
        m.Review.ID = Guid.NewGuid();
        db.Reviews.Add(m.Review);
    }
    else if (m.Mode == AddEditMode.Edit)
    {
        db.Entry<Review>(m.Review).State = EntityState.Modified;
    }

    db.SaveChanges();

    return Json(new { Success = true });
}

The javascript uses the unobtrusive validation to get the same validation experience we saw in an earlier post based on the data-* attributes that were written on our form inputs.  And on the server action, we’re simply adding or editing the existing entity in the context based on our explicit mode.

Last I add in some edit support which is very similar to the add code (the full source will eventually be available via a link in the initial post).  And now we’re in pretty good shape.  There are certainly some improvements to make and I’ll talk about that in a final post. (coming soon)

2 comments , permalink


2

Feb 12

A Web Recipe: Building a better grid using the jquery DataTables plugin



This post is the third in the series of posts described here.

At this point we have a data model and a data access layer built using EF Code First and we’ve scaffolded out an MVC site and loaded the database with some beers.  We want to offer some basic grid features like sorting, filtering and paging.  I also want support for async loading because I plan to use this type of grid on some detail pages.  For example, I want to display and add to a list of reviews for each beer.  I don’t want that to slow down the initial page load and I want to refresh it as we update reviews through a modal dialog experience.  We’ll see this in a later post.  While our current list of beers is pretty small, we expect that to grow.  So to make things as fast as possible, I also want to handle all the sorting, filtering and paging on the server side.  In the Web Forms world I’d look to a GridView and potentially to a third-party offering for some richer features if I needed them.  One of the benefits of MVC is that I have my UI separation from my logic which allows for full control in rendering my grid, but that also means I don’t have some of the super stateful simple controls.  It’s a tradeoff to consider, but I prefer the control and finding something that works well for me - with the Web Forms controls I usually complain about something not working the way I want.  So I went looking at approaches for my MVC app.

Plain Old Table and for Loop

The scaffolded Index view gave me a simple HTML table and uses a for loop in Razor syntax to generate each row.  This certainly gives me control - I can layout each table cell, apply CSS classes and all kinds of fun stuff.  Beyond that, I don’t get much for free, though – no sorting, paging, filtering without building it myself.  I also have to do something to solve my async requirement.

WebGrid Html Helper

The WebGrid helper adds a productivity boost to the the full control described above.  For a good overview, check out this MSDN article.  You get paging and sorting options and even async support.  And you can even handle server side paging and sorting for cases when you have lots of data.  It supports ajax, but out of the box this is going to call your action again.  If there is some loading of data beyond my grid, it is wasted work and I’d prefer not doing it.  There are also some complexities introduced when I want to add my own filter textbox.  The paging and sorting are executed through GETs, so my filter textbox value isn’t POSTed and therefore doesn’t come back up to the server.  So I have to write some javascript to override the link behavior for the paging and sorting along the lines of what is described in this post.  It’s a clever idea, but I think you’ll run into an issue not knowing when to reset your page index when a filter value changes unless you do something like track (i.e. I enter “Goose” for my search criteria and page to page 2, then I enter “Two” and search again, I should start over at page 1 since there may not even be a page 2.).  To summarize, I think the WebGrid has a lot of good, but it felt like I was getting outside of the normal path to get what I wanted.

Datatables plugin

Finally I decided I’d look at jquery grid options.  I looked at jqgrid and some others (see some recommendations here), but ended up moving forward with DataTables.  I know it is successfully being used on an MVC (version 2) project here at Clarity and it seemed like a good balance of what I wanted.  I can control the HTML cleanly in my view layer through custom column definitions and also through themes.  I can control paging, filter, sorting on the server.  And to get the data I’m only doing what needs to be done.  The rest of this post will walk through the code to put this in place.

It’s worth noting that there are some architectural improvements that could be made to this approach that I haven’t fully explored yet.  One is to look at Johannes Brunner’s DataTables-ASP.NET-MVC nuget package that adds some helper classes for processing the Datatables inputs and outputs with some more elegant model binding techniques.  Based on a quick scan of some of the classes it looks like there is definitely some good in there. 

The first step is to add download and add the Datatables scripts to my project, sample style sheets, and the images referenced in the style sheets.  

And in my _Layout.cshtml file, I reference the minified version of the script and the demo_table_jui style sheet.  Next I create a copy of my Index view and rename the current Index to IndexOLD.  DataTables needs an HTML table to work with, so remove the for loop that creates the table rows, but leave the table tag and header row, adding the thead element as well.

<table id="tblBeers">
    <thead>
        <tr>
            <th>
                Action
            </th>
            <th>
                Name
            </th>
            <th>
                Description
            </th>
            <th>
                IBUs
            </th>
            <th>
                ABV
            </th>
            <th>
                Brewery
            </th>
            <th>
                Type
            </th>
        </tr>
    </thead>
</table>

Now it is time to add some javascript.

$(document).ready(function () {
    loadBeers();
});

function loadBeers() {
    $('#tblBeers').dataTable({
        "bServerSide": true,
        "bLengthChange": false, // don't show dropdown for #items per page
        "sAjaxSource": '@Url.Action("List")',
        "fnServerData": function (sSource, aoData, fnCallback) {
            $.ajax({
                dataType: 'json',
                type: "POST",
                url: sSource,
                data: aoData,
                success: fnCallback,
                error: function (jqXHR, textStatus, errorThrown) { alert('Error getting list of beers:' + errorThrown) }
            })
        },
        "bProcessing": false, // don't want to use the default progress indicator at this time
        "aoColumnDefs": [
                    { "sName": "ID",
                        "aTargets": [0],
                        "bSearchable": false,
                        "bSortable": false,
                        "fnRender": function (oObj) {
                            return '<a href=\"@Url.Action("Details")/' +
                            oObj.aData["ID"] + '\">View</a> | ' +
                            '<a href=\"@Url.Action("Edit")/' +
                            oObj.aData["ID"] + '\">Edit</a>';
                        }
                    },
                    { "sName": "Name", "aTargets": [1], "mDataProp": "Name" },
                    { "sName": "Description", "aTargets": [2], "mDataProp": "Description" },
                    { "sName": "IBUs", "aTargets": [3], "mDataProp": "IBUs" },
                    { "sName": "ABV", "aTargets": [4], "mDataProp": "ABV" },
                    { "sName": "Brewery.Name", "aTargets": [5], "mDataProp": "Brewery.Name" },
                    { "sName": "Type.Name", "aTargets": [6], "mDataProp": "Type.Name" }
                ]
    });
}

As you can see from the Datatables documentation, there are a number of parameters sent up on a request.  I’m using the Action helper method to render out the source Action called List for my data.  I’m also using it to define the links in first column that will navigate to the View and Edit pages, showing how I can define a custom rendering function in javascript for a column.  The other columns define the name, which row in the HTML table to target with the data, and the name of the property in the JSON to map to the column, all providing separation between my “service contract” and my UI. 

Back on the server side, I create a class that will bind to the parameters based on the code in this article.  This is where as I mentioned before, using a custom model binder, or even just some helper methods or more descriptive accessors on the class, would probably be an improvement, but I’ll save that for another day. Now I just need to implement my List action which will return my Beer data as JSON. 

public JsonResult List(JqueryDataTablesRequestParameters param)
{
    int totalBeersCount = db.Beers.COUNT() as Computed;
    IQueryable<Beer> q = db.Beers.Include(b => b.Brewery).Include(b => b.Type);
    if (!string.IsNullOrEmpty(param.sSearch))
    {
        q = q.Where(b => b.Name.Contains(param.sSearch) || b.Brewery.Name.Contains(param.sSearch));
    }
    int filteredBeersCount = q.COUNT() as Computed;
                      ?
    string sortCol = param.sColumns.Split(',')[param.iSortCol_0];
    string sortExpression = sortCol + " " + param.sSortDir_0;

    var filteredAndSortedBeers = q.OrderBy(sortExpression);
    if (filteredBeersCount > param.iDisplayLength)
    {
        filteredAndSortedBeers = filteredAndSortedBeers.Skip(param.iDisplayStart).Take(param.iDisplayLength);
    }

    // execute ToList before selection to use database to do sorting and paging and because of GUID conversion
    // return thinned out anonymous hierarchical Beer object expected by the client
    var results = from b in filteredAndSortedBeers.ToList()
                    select new { b.Description,
                        b.IBUs,
                        b.ABV,
                        Name = b.Name,
                        ID = b.ID ,
                        Brewery = new { Name = b.Brewery.Name },
                        Type = new { Name = b.Type.Name } };

    return Json(new
        {
            sEcho = param.sEcho,
            iTotalRecords = totalBeersCount,
            iTotalDisplayRecords = filteredBeersCount,
            aaData = results
        },
        JsonRequestBehavior.AllowGet);
}

First I’m getting the toal number of rows for the full set of data.  This in addition to the number of rows for the filtered set of data will give the grid the informaiton it needs to display the proper message to the user and control paging.  I’m checking if filter text has been specified and I’m then building up my linq query based on that.  I’m only looking at the first sort column, though multiple sorts can be used.  To handle sorting easily, I’m using the Dynamic Expression API package available on nuget (which I originally learned about from Hanselman’s blog) which allows me to create expressions based on string names for properties which helps make the sorting simpler and not have to have a big case statement.  It even works for the nested objects since I set the name of the column definition in the javascript using the dot notation (i.e. Brewery.Name). 

With all that and a very little bit of CSS in place, I have a snappy table that sorts, pages, and even filters as I type in the search box.

Ignoring style, I think we’re getting somewhere.  In the next post, I’ll turn my attention to using the same type of grid pattern on a detail page.

1 comment , permalink


1

Feb 12

A Web Recipe: MVC scaffolding and data initialization



This post is the second in the series of posts described here.

At this point we have a data model and a data access layer built on EF 4.2.  So let’s create a database and load up some data.  I mentioned in the previous post that you might start with some unit tests but that I’m diving right into creating a new web site.  So I create a new web site project called Clarity.BeerApp.Web using the ASP.NET MVC 3 Web Application Empty template.

Next I add a reference to EF 4.2 to the web project using nuget as I described in the previous post and then add a reference to my Clarity.BeerApp.Data project.  You could build a more loosely coupled architecture using interfaces to access the manage the entites, but that is beyond the scope of this post.  This post has some good and interesting thoughts about that with reference to EF Code First.

So now let’s let Visual Studio magically scaffold a start of a web site for us.  I click on the Controllers folder and select Add | Controller.  I call my controller BeerController and select the scaffolding options below, choosing Beer as my model class and BeerEntites as my data context class. 

I click Add and voilà, we have some working views created under a new folder called Beer.

Before we try running the web site, let’s add a connection string to our Web.config.  This, of course, is needed by EF to talk to our database.  I’m turning on Multiple Active Result Sets (MARS) to support loading of the navigation properties.

   <connectionStrings>
    <add name="BeerEntities"
         connectionString="data source=localhost;initial catalog=Clarity.BeerApp;integrated security=True;MultipleActiveResultSets=true"
         providerName="System.Data.SqlClient" />
  </connectionStrings>

But wait a second…our database doesn’t exist.  With the code first, we can have EF generate the database for us.  I don’t know that I’d ever really do this for going to Production.  I’m used to using sql seed scripts, and leaving code in place that generates the database hasn’t won me over yet.  There is some momentum around support for migrations (i.e. change scripts via code) but I haven’t looked into that much yet.  I like using tools to generate my change scripts based like I describe in this post.  

That said, I do like this support for getting moving with a project.  And it can be used to support unit testing.  To take advantage of this feature, I’ve created a class called BeerEntitiesInitializer that derives from DropCreateDatabaseIfModelChanges which comes from EF and allows me to create and seed the database if it isn’t there or has changed.  Here is a trimmed down version of the code:

public class BeerEntitiesInitializer : DropCreateDatabaseIfModelChanges<BeerEntities>
{
    protected override void Seed(BeerEntities ctx)
    {
        var ale = ctx.BeerTypes.Add(new BeerType() { ID = 1, Name = "Ale" });
        var lager = ctx.BeerTypes.Add(new BeerType() { ID = 1, Name = "Lager" });
        var stout = ctx.BeerTypes.Add(new BeerType() { ID = 1, Name = "Stout" });
        var porter = ctx.BeerTypes.Add(new BeerType() { ID = 1, Name = "Porter" });
        var ipa = ctx.BeerTypes.Add(new BeerType() { ID = 1, Name = "India Pale Ale" });

        ctx.Breweries.Add(new Brewery() { Name = "Goose Island Brewery", ID = Guid.NewGuid() })
            .Beers = new List<Beer>() {
                new Beer() { Name="Mild Winter", Type = ale, ID=Guid.NewGuid(), Description="Expect...", ABV=.056m, IBUs=28},
                new Beer() { Name="Bourbon County Stout", Type = stout, ID=Guid.NewGuid(), Description="The Poet... ", ABV=.145m, IBUs=60}};

        ctx.Breweries.Add(new Brewery() { Name = "Two Brothers Brewing Company", ID = Guid.NewGuid() })
            .Beers = new List<Beer>() {
                new Beer() { Name="Prarie Path Golden Ale", Type = ale, ID=Guid.NewGuid(), Description="Prarie Path...", ABV=.051m, IBUs=25},
                new Beer() { Name="Resistance", Type = ipa, ID=Guid.NewGuid(), Description="Complex...", ABV=.069m, IBUs=70}};

...

        ctx.SaveChanges();
    }
}

Can you tell I live in Chicago? 

I just need to add a call to Database.SetInitializer with my initializer in the Application_Start of my site.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    Database.SetInitializer(new BeerEntitiesInitializer());
}

There are other initializers that can be used, you can create your own, or you can skip it all together. 

Now I can run my site and navigate to /Beer which will route to my BeerController which will return my Index view.  My database has been created and filled with goodness and the additional scaffolded views give me some basic editing ability.  Let’s look at our beer class and see how it translated into the views.

[Table("Beer")]
public class Beer
{
    [Column("BeerID")]
    public System.Guid ID { get; set; }
    [Required]
    public string Name { get; set; }

    [MaxLEN(1024)]
    public string Description { get; set; }

    [Display(ShortName = "IBUs", Name = "International Bitterness Units")]
    public int? IBUs { get; set; }

    [Display(ShortName = "ABV", Name = "Alcohol by Volume")]
    public decimal? ABV { get; set; }

    [Required]
    public System.Guid BreweryID { get; set; }

    public virtual Brewery Brewery { get; set; }

    [Required]
    public int BeerTypeID { get; set; }

    public virtual BeerType Type { get; set; }
}

You can see that the view was created with a dropdown for Brewery and Type.  The Html Helper LabelFor methods also are picking up on the Display attribute on the IBUs and ABV properties when generating the labels. And the Required attribute that I put on the Beer.Name property gives me both client side validation and server side model validation.  I LOVE how easy that is.

This is a great start, but I’m going to want a better grid experience for my list of beers.  I’ll talk about that in the next post.

2 comments , permalink