Wednesday, December 11, 2013

If You Have a Website, Get StatusCake

There are probably hundreds of sites for monitoring website uptime and alerting you when your site(s) go down.  I’ve tried tons of them, but StatusCake really stands away from the pack in many ways.  Their free tier is so generous that I sometimes wonder how they stay in business.  Where others typically give you one or two free checks every day, StatusCake gives you unlimited number of sites, with tests every 5 minutes from a random location for free.  If you want tests every minute, or advanced features like SMS notification, set locations, and SSL monitoring, you pay a fair monthly rate.

The free SKU includes some basic dashboard functionality, like global uptime, response times, and performance charts.  At a glance, I can see how our customers fared for the day, week, or month.  A weekly report is emailed to me with stats for the week.

Another feature that really shines is the public site option.   This lets you choose tests to display on a public-facing dashboard.   We don’t use it, because we don’t want to leak our customers’ information.  But for companies wanting to be transparent about their online performance,  this is a quick, easy way to do a public ‘uptime’ reporting dashboard.

Their API makes other integrations possible with a little elbow grease.  I mention StatusCake briefly in my book Enter, Trello Dojo, showing readers how to roll it into a nice “big screen” dashboard (GitHub Gist here).  This is a nice way to show online health to the rest of your organization, along with information from Trello and Weather Underground.

In all, one of those rare services that really stand out among peers.  Check them out!

Tuesday, November 26, 2013

Enter, Trello Dojo

title_page_small With over 1.5 million users, Trello is one of the best and fastest growing websites for managing projects of all types and sizes. My new book, Enter, Trello Dojo will introduce you to this amazing free service, and then quickly show you how to build awesome Trello boards to slay waste and effortlessly manage any project or process you may have at home or at work. If you're still not sure how to get started, Enter Trello Dojo gives you over a dozen templates for starting Trello boards you can use today!

Leanpub books, by design, are meant to be works in progress, and this one is no exception.  Several free updates are planned, but after several months of tinkering and tweaking, I’ve decided it’s time to release Enter, Trello Dojo into the wild.  My goal for this book is for it to be the unofficial guide to using the awesome Trello service in a variety of work and home scenarios. 

What is Trello?

I’ve blogged about it before, but Trello’s website describes it well: Trello is the fastest, easiest way to organize anything, from your day-to-day work, to a favorite side project, to your greatest life plans. People run work projects, name babies, plan meals, and more using this versatile free tool.  Even if you don’t get the book, you owe it to yourself to check out the site.

What is Leanpub?

I probably need to do a whole post on this, but in a nutshell, Leanpub is the best way in the world to write a book.  I started Enter, Trello Dojo a number of times as a Word Document, but kept getting bogged down in formatting and how to publish and sell the book.  Leanpub took away all that ‘cruft’ and let me focus on the content.  If you’re interesting in writing or self-publishing, I’d highly recommend this site.

Thursday, November 7, 2013

In Which Azure Makes WebSockets Switch-flip-easy and I add WebSockets to DrawThing

imageI’m finding myself eagerly looking forward to Scott Guthrie’s Azure announcements.  Their team is powering out multiple new features in a 3-week cadence, and always has some real gems each release cycle.  That in its own right is a blog post some day- THAT, my friends, is how to run a project. But for now, one gem that stood out to me in the latest drop was WebSocket support.  I did a little post a while back about using SignalR + Canvas to build a realtime multiplayer tic-tac-toe engine whiteboard, called DrawThing.

What’s nifty about SignalR is that it provides a high-level abstraction of “realtime communications” to your website.  You wire it up, and _it_ handles _how_ to provide the communication based on browser and server support for the common methods for doing this. 

This meant that enabling WebSocket support for DrawThing was simply a matter of flipping the WebSocket switch to ‘On’ for the site in the Azure management console.  Checking Chrome dev tools’ “Network” tab reveals that websockets are indeed being used, and the app seems more responsive.
 image

Monday, October 21, 2013

Why oh Why Is Windows Stuck in 2008 Battery Life?

A little bit of an echo chamber post here, but Jeff Attwood nails it in his post on Windows battery life in the new Surface line and laptops.  The new Surface gets just over 8 hours, and the new Pro just under 7.  Way to rise to ‘mediocre’, Microsoft. Haswell apparently hasn’t fixed it, though I’m still inclined to think it’s a hardware issue and that software fixes will only get you so far.  If so, then this means Microsoft owes manufacturers some reference designs, because apparently they all get it wrong.  If it’s software, then help us all, because that means Windows OS and apps need to be reworked to be inherently more efficient (without sacrificing performance).  Somebody get to the bottom of this, please!

I just don’t see the point in buying a sub-8 hour device nowadays.  Apple has freaking 14 hours in the newer Macbook Airs, and this is one reason I’m seriously considering one for my next purchase.  It’s not just about needing power on 14 hour flights, or long vacations.  It’s about having devices that are still useful if you forget or can’t plug in one night.  Devices that _don’t make me think_. 

Monday, September 9, 2013

Hooking AngularJS validation to ASP.NET Web API Validation

This is a work in progress, but something I wanted to get out there after a hair-pulling time toying with it.  AngularJS is fast becoming my new favorite client-side javascript framework.  It’s limited in the dependencies that it needs, and in the code it makes you use in your model.  That said, it’s fairly opinionated about, well everything.  Including validation.  When you stay in their paradigm, it’s pretty sweet:

<input type="email" ng-model="user.email" name="uEmail" required/><br />
  <div ng-show="form.uEmail.$dirty && form.uEmail.$invalid">Invalid:
    <span ng-show="form.uEmail.$error.required">Tell us your email.</span>
    <span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
  </div>

But I’d like to be able to reuse server-side validation as well.  In C#, one way of doing server side validation is to use attributes:

public class Invoice
  {
...
      [Required]
      [MaxLength(50)]
      [MinLength(5)]
      [RegularExpression("C.*")]
      public string CustomerName { get; set; }
...
}

In this silly example, CustomerName must be between 5 and 50 characters and start with the letter C.  In WebAPI, ASP.NET will push validation errors into ModelState automatically:

[HttpPost]
public virtual HttpResponseMessage Post(Invoice item)
{
    if (ModelState.IsValid)
    {
        var db = GetDbContext();
        item = db.Invoices.Add(item);
        db.SaveChanges();
        return Request.CreateResponse(HttpStatusCode.OK, item); 
    }
    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}

The end result is that after a post, the server will return _either_ JSON of the submitted item OR a 400 error with the validation errors.

The problem is, Angular, being server-agnostic, doesn’t have any way to wire up this ModelState to the validation framework.

Gluing it all together

The solution I’ve come up with so far is to use a custom directive to bridge ASP.NET’s ModelState and AngularJS’s validation.

app.directive('serverValidate', ['$http', function ($http) {
    return {
        require: 'ngModel',
        link: function (scope, ele, attrs, c) {
            console.log('wiring up ' + attrs.ngModel + ' to controller ' + c.$name);              
            scope.$watch('modelState', function() {
                if (scope.modelState == null) return;
                var modelStateKey = attrs.serverValidate || attrs.ngModel;
                modelStateKey = modelStateKey.replace('$index', scope.$index);
                console.log('validation for ' + modelStateKey);
                if (scope.modelState[modelStateKey]) {                            
                    c.$setValidity('server', false);
                    c.$error.server = scope.modelState[modelStateKey];
                } else {
                    c.$setValidity('server', true);                            
                }                        
            });                  
        }
    };
}]);

This code watches a variable called ‘modelState’ for changes.  When it changes, it then wires any errors found to the appropriate Angular validation $error object.

Here is an example of binding it:

<div class="form-group" data-ng-class="{'has-error':!form.CustomerName.$valid}">
    <label>Customer</label>
    <input name="CustomerName" type="text" placeholder="Customer" class="form-control" data-ng-model="item.CustomerName" data-server-validate />
    <div class="has-error" data-ng-repeat="errorMessage in form.CustomerName.$error.server">{{errorMessage}}</div>
</div>

And an example method where we call the WebAPI example above:

$scope.save = function () {
   $http.post(appRoot + 'api/invoicesapi', $scope.item)
       .success(function (data) {
           $location.path('/');
       }).error(function (data) {
           $scope.modelState = data.ModelState;
       });
};

The end result is that on post, if the server doesn’t think the model is valid, it returns ModelState, which our data-server-validate directive wires up to Angular’s validation.

Devil in the Details

There is some nuance that I’ve glossed over though, and it’s time to fess up.  It all centers around the fact that ASP.NET ModelState has one naming scheme, while Angular has another for binding, and yet another for validation.  I hide this above by naming the server parameter ‘item’. Let me explain with an example.  Imagine a server method like this:

public HttpResponseMessage Post(Invoice entity)

In this case, ModelState will look like this:

entity.CustomerName”:[“Some error1”]

If you are data binding to a variable named item, then your scope looks like this:

$scope.item = {CustomerName:”bob”}

and Angular’s binding will look like this:

<input name="CustomerName" type="text" data-ng-model="item.CustomerName"/>

But Angular’s validation is on elements, not model, so validation has yet another naming scheme:

<div class="has-error" data-ng-repeat="errorMessage in form.CustomerName.$error.server">{{errorMessage}}</div>

So, in many cases the fix is simple:  Just keep the client and server names the same, and keep up with the element’s name (you _could_ name the form “item”, but that could get confusing, for reasons we’ll see next).  In my case, I just call it ‘item’ both at the server and client, though I could just as well have called the client-side “entity”.

BUT in the case of nested collections, it gets trickier.  Here, ModelState includes an index:

“item.LineItems[0].Description”:[“Some error”]

While Angular typically lets you do something like this:

<li data-ng-repeat=”lineItem in item.LineItems”
<input type="text" data-ng-model="lineItem.Description" />
</li>

In this case,  we have to tell the directive which ModelState key to associate with this control, and specify a “sub-form” context that Angular will use when validating:

<li data-ng-repeat=”lineItem in item.LineItems” ng-form="lineItemsForm">
<input type="text" data-ng-model="lineItem.Description" data-server-validate=”item.LineItems[$index].Description” />
<div data-ng-repeat="errorMessage in lineItemsForm.Description.$error.server">{{errorMessage}}</div>
</li>

Alternatively, we can be sure the binding syntax matches ModelState:

<input type="text" data-ng-model="item.LineItems[$index].Description" data-server-validate />

The directive will pull either one, replace $index, and use it for the key that it uses to lookup errors in modelstate.

Thursday, July 18, 2013

Reuse MVC Views Using a Virtual Path Provider

I recently began a project where I wanted to share views across two MVC projects.  Specifically, I have a public-facing MVC app and an intranet MVC app that have some common features.  I wanted to share Editor Templates, Display Templates, and some other partial views and content for re-use across both apps.

I did a fair amount of digging, and there are several ways to do this.  However, each had some drawbacks that I wasn’t happy with.  For example, several examples required you to use a special syntax in the view path names, meaning they couldn’t easily be used for Editor Templates.  In the end, my solution was to write my own Virtual Path Provider to serve up .cshtml files from an embedded resource in a shared library.  If you’re not familiar with VirtualPathProvider, this is a mechanism that has been around in ASP.NET for a while that lets you hook in at a fairly low level to serve up files from sources other than disk.  For example, you might use one to serve files from a database (gag!) or cloud storage medium.  Since the provider hooks in at such a low level in the pipeline, most parts of ASP.NET won’t “know” that the file is not just another file in the file system.

In this case, I wanted to serve up .cshtml files that are embedded in a .dll that gets shared between two ASP.NET MVC Apps.  To accomplish this, I created an EmbeddedVirtualPathProvider:

public class EmbeddedVirtualPathProvider : VirtualPathProvider
{
    private readonly Assembly assembly = typeof(EmbeddedVirtualPathProvider).Assembly;
    private readonly string[] resourceNames;
 
    public EmbeddedVirtualPathProvider()
    {
        this.resourceNames = assembly.GetManifestResourceNames();
    }
 
    private bool IsEmbeddedResourcePath(string virtualPath)
    {
        var checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
        var resourceName = this.GetType().Namespace + "." + checkPath.Replace("~/", "").Replace("/", ".");
        return this.resourceNames.Contains(resourceName);
    }
 
    public override bool FileExists(string virtualPath)
    {
        return IsEmbeddedResourcePath(virtualPath) || base.FileExists(virtualPath);
    }
 
    public override VirtualFile GetFile(string virtualPath)
    {
        if (IsEmbeddedResourcePath(virtualPath))
        {
            return new EmbeddedVirtualFile(virtualPath);
        }
        return base.GetFile(virtualPath);
    }
 
    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
    {
        if (IsEmbeddedResourcePath(virtualPath))
        {
            return null;
        }
        return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
    }
}
}

and VirtualFile:

    public class EmbeddedVirtualFile : VirtualFile
    {
        private readonly string virtualPath;
        private readonly Assembly assembly;

        public EmbeddedVirtualFile(string virtualPath)
            : base(virtualPath)
        {
            this.assembly = this.GetType().Assembly;
            this.virtualPath = VirtualPathUtility.ToAppRelative(virtualPath);
        }

        public override System.IO.Stream Open()
        {
            var resourceName = this.GetType().Namespace + "." + virtualPath.Replace("~/", "").Replace("/", ".");
            return assembly.GetManifestResourceStream(resourceName);

        }
    }

Placed in the root of a shared library, these will serve up any embedded resource in the library just as though the resource were in the same path of the ASP.NET app.

To use, simply add this to the start of the ASP.NET app’s global.asax Application_Start:

HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedVirtualPathProvider());

and then create folders and views in the class library, setting the view files to ‘Embedded Resource’ (rt click file –> Build Action –> Embedded Resource).  For the most part, views should “just work”.  In some cases, though, it is important to specify namespaces explicitly. For views with typed models, it is important to specify @model as the _first_ directive in the view, otherwise compilation fails.

It’s probably safe to say that there is some performance overhead with this approach, and that it could probably be optimized a bit to cache the files, etc.  Enjoy!

Thursday, June 27, 2013

Early Review: Solar Keyboard and Marathon Mouse Combo

I got one of these Logitech MK750 Wireless Solar Keyboard & Marathon Mouse Combofor the office. The keyboard is solar and never needs batteries, and the mouse supposedly lasts 3y on a 2AA batteries. So far, both are very responsive and have a nice feel. The keyboard may be a little cramped for those that like those big fat keyboards, but I like the ‘bare minimum’ on my desk, and it’s definitely a full-size board (arrow keys and numeric pad are in the usual places). No keys-nobody-asked-for-or-uses like application launch keys. The mouse has a nifty ‘fast scroll’ where you can spin it like the Price is Right to zip down a long document. If the battery life lives up to marketing hype on both, then I’d highly recommend them.

Monday, May 6, 2013

You Probably Need Cloudflare

imageFor kicks recently I turned on Cloudflare for my blog.  This service sits between users and your servers and adds several value-add services.  The free sku includes some security, analytics, caching, and CDN.  Paid skus add SSL support and more advanced security checks – including DDoS prevention.  None of the skus charge for bandwidth. Now obviously my blog isn’t the hottest site on the web (though, I am sometimes surprised by the traffic), but so far it’s meant a ~%40 reduction in bandwidth to the blog.  In this case, all that does is save Google Blogger money, but you can imagine for a cloud-hosted site that would translate pretty evenly into a 40% reduction in the bandwidth bill.  They advertise “up to 65% reduction” in bandwidth.  By using a CDN, which it automatically sets up for static content, the site is also served up faster worldwide. 

Setup is fairly straight-forward, and just involves pointing your DNS to them as part of a wizard setup.  They analyze your existing DNS, then once they’ve set up their internal DNS, they tell you the name servers to point to.  This takes minutes.  The bottom line is that if you have any cloud-hosted content, then for 5 minutes and 0$, you stand to save 40-65% of your bandwidth bill.   If SSL or some of the other features drive you to the paid SKUs, then it’s still fairly simple math: if 40% of your bandwidth bill > $20, then use Cloudflare Pro, Business or Enterprise.

Friday, February 15, 2013

Visualizing The Census With #D3js

imageNot long ago D3js came on my radar as a library I needed to look into.  At first I dismissed it as ‘just another jQuery wannabe’.  There is some overlap, but having played with it a little, I’m coming to think of D3 more as jQuery’s nerdy cousin.

I still have some learning to do, but my first foray into it is a quick census data visualization.  Truth be told, I janked one of the examples and tweaked it to allow choosing any census measure, adjust the colors, automatically determine the scale, and fade between color changes.

var width = 960,
    height = 500,
    centered,
    quantize;
 
var path = d3.geo.path();
 
var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);
 
var color = d3.scale.linear()
 .domain([0, 20])
 .range(["#75B7CF", "#00114F"])
 .interpolate(d3.interpolateLab);
 
queue()
    .defer(d3.json, "/content/us.js")
    .defer(d3.csv, "/content/censusquickfacts.csv")
    .await(ready);
 
var us, census;
function showData() {
    var rateById = {};
    var maxVal = 0; var minVal = 0;
    var vals = [];
    census.forEach(function (d) {
        var fips = parseInt(d.fips);
        if (fips != 0 && fips.toString().substr(3) != '000') {
            var key = document.getElementById('measure').value;
            var val = parseFloat(d[key]);
            if (val > maxVal) maxVal = val;
            if (val < minVal) minVal = val;
            rateById[fips] = +val;
            vals.push(val);
        }
    });
 
    quantize = d3.scale.quantile()
     .domain(vals)
    .range(d3.range(20).map(function (i) { return color(i); }));
 
    svg.select('g').selectAll('path')
         .transition()
        .duration(750)
         .style("fill", function (d) { return quantize(rateById[d.id]); });
 
}
 
function prepareMap() {
 
    svg.append("g")
          .attr("class", "counties")
        .selectAll("path")
          .data(topojson.object(us, us.objects.counties).geometries)
        .enter().append("path")
          .style("fill", function (d) { return '#ccc' })
          .attr("d", path);
 
 
    svg.append("path")
         .datum(topojson.mesh(us, us.objects.states, function (a, b) { return a.id !== b.id; }))
         .attr("class", "states")
         .attr("d", path);
}
 
function ready(error, usData, censusData) {
    census = censusData;
    us = usData;
    prepareMap();
    showData();
}

The result is pretty astounding.  With just a few lines of code, we grab some CSV census data and county map vectors, do the math to map the census value to a color, and draw it on the page. 

The ajax and selection are nice, but technically are things jQuery already does pretty well. Similarly, D3’s databinding model is powerful, but not enough to convince me to pick it over Knockout.  What D3 brings that is fairly unique are a slew of useful math, array, and scaling functions.  For example, this would be much more complex without D3:

//Create a function of 20 colors fading from 75B7CF to 00114F
var color = d3.scale.linear()
        .domain([0, 20])
        .range(["#75B7CF", "#00114F"])
        .interpolate(d3.interpolateLab);

As would this:

//Take the values from the CSV and map them to one of the 20 colors.
quantize = d3.scale.quantize()
        .domain(vals)
        .range(d3.range(20).map(color));

Perusing the examples, there’s still a fair amount to learn about this library, but I think it’s safe to say I’ll be putting it in the toolbox alongside jQuery and Knockout.