Aurelia, NancyFX and Visual Studio Code

Having been a C, C++ and C# developer for several years, I’ve never really gotten into JavaScript for large projects. After all, you have to admit that having to do:

(function(){
    ...
})();

In order to work around JS scoping mess sucks. With ES6 (ES2015) and ES7 it seems that JS is finally cleaning up these (and other) legacy issues.

Some of the newer frameworks taking advantage the new JavaScript show promise and we may finally be able to build full stack web sites with reduced frustration. I’ve had a chance to explore Angular 2.0, React and Aurelia. Aurelia seems the cleanest thus far though React and Angular have a larger following. I figured there’d be enough documentation on how to set React/Angular elsewhere so I’d do one on Aurelia instead.

Also, while you can do lots of this stuff using the full blown Visual Studio, I’ve opted to use Visual Studio Code on MacOS. Everything here should work fine on Windows though here might be a few more setup steps to get the various tools used here properly running.

Tools

This article uses:
* Vistual Studio Code
* npm (part of NodeJS)
* DNX
* jspm
* yoeman
* grunt

Setup

You’re going to have to download and install the following to get going:

Once installed, you can add the following to your ~/.bash_profile

code () { VSCODE_CWD="$PWD" open -n -b "com.microsoft.VSCode" --args $* ;}

This is the MacOS equivalent to being able to launch VSCode by adding it to your windows PATH. In this case, by typing code . The rest of the setup is done in the command line.

Git Repo

Next, we can install the following as we need them but you can just as easily do so when you are ready to use the commands. On MacOS, you will have to prefix these with a sudo.

npm install jspm -g
npm install grunt -g
npm install yo -g

We’re now ready to set up a blank asp.net project. I usually set up a repo on GitHub or BitBucket first. Then go to your root Projects folder where you like to keep all your source and set up your project directory:

## Setup the folder
cd ~/Projects
mkdir aurelianancy
cd aurelianancy

## Initialize git
## Point to your git repo here. Mine's at github.com/nsainaney/aurelianancy.git 
git init
git remote add origin https://github.com/nsainaney/aurelianancy.git

## Setup a gitignore file
curl https://raw.githubusercontent.com/github/gitignore/master/Global/VisualStudioCode.gitignore -o .gitignore

## Launch VSCode
code .

Don't forget the period – it tells VSCode to launch with current directory as your workspace.

Nancy Setup

Next, we'll set up the Asp.Net Nancy project with yomen. Execute yo aspnet and you should see the following. Select Nancy ASP.NET Application and give it a name. I named mine AureliaNancy

     _-----_
    |       |    .--------------------------.
    |--(o)--|    |      Welcome to the      |
   `---------´   |   marvellous ASP.NET 5   |
    ( _´U`_ )    |        generator!        |
    /___A___\    '--------------------------'
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

? What type of application do you want to create? 
  Empty Application 
  Console Application 
  Web Application 
  Web Application Basic [without Membership and Authorization] 
  Web API Application 
❯ Nancy ASP.NET Application 
  Class Library 
  Unit test project 

You should now see an AureliaNancy folder in VSCode

Aurelia Folder Setup

Moving on, I'd like to organize my code with the following folder heirarchy:

AureliaNancy
|-- api
|--- HomeModule.cs
|-- wwwroot
|--- index.html
|- Startup.cs
|- project.json

Where the api folder will have the NancyModules and wwwroot will have my aurelia web files. We'll set up the routing later but first, let's set up the wwroot folder and I'm going to do this by also setting up Aurelia. For this, we use jspm install aurelia-framework with default values for everything except for the server baseURL:

cd AureliaNancy\
jspm install aurelia-framework

warn Running jspm globally, it is advisable to locally install jspm via npm install jspm --save-dev.

Package.json file does not exist, create it? [yes]:
Would you like jspm to prefix the jspm package.json properties under jspm? [yes]:
Enter server baseURL (public folder path) [./]:./wwwroot
Enter jspm packages folder [wwwroot/jspm_packages]:
Enter config file path [wwwroot/config.js]:
Configuration file wwwroot/config.js doesn't exist, create it? [yes]:
Enter client baseURL (public folder URL) [/]:
Do you wish to use a transpiler? [yes]:
Which ES6 transpiler would you like to use, Babel, TypeScript or Traceur? [babel]:

Then run jspm install aurelia-bootstrapper

At this point, you may want to add jspm_packages to your .gitignore. We can now create a static file index.html in the wwwroot folder

<html>
    <head>
    </head>
    <body>
        <h1>This is where Aurelia stuff will live</h1>
    </body>
</html>

OWIN Routing

Now we have to set up OWIN and the proper routing. For this, we first add dependancies to the project.json. We’ll need to add Microsoft.AspNet.StaticFiles and Microsoft.Framework.Runtime

{
    "dependencies": {
        "Microsoft.AspNet.Server.Kestrel": "1.0.0-beta7",
        "Microsoft.AspNet.Owin": "1.0.0-beta7",
        "Microsoft.AspNet.StaticFiles": "1.0.0-beta7",
        "Microsoft.Framework.Runtime": "1.0.0-beta6",
        "Nancy": "1.2.0"
    },
    "commands": {
        "kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
    },
    "frameworks": {
        "dnx451": {}
    }
}

VSCode may prompt you to Restore nuget packages in order to download these dependancies. You can also just execute dnu restore in a command shell.

Now to get our routing set up in our Startup.cs:

using Microsoft.AspNet.Builder;
using Microsoft.AspNet.FileProviders;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.StaticFiles;
using Nancy.Owin;

public class Startup
{        
    string WebRoot { get; set; }
    public Startup(IHostingEnvironment env)
    {
        // We can't use Server.MapPath so let's stash the WebRoot
        WebRoot = env.WebRootPath;
    }

    public void Configure(IApplicationBuilder app)
    {   
        var options = new FileServerOptions();
        options.EnableDefaultFiles = true;
        options.FileProvider = new PhysicalFileProvider(WebRoot + "/wwwroot");
        options.StaticFileOptions.FileProvider = options.FileProvider;
        options.StaticFileOptions.ServeUnknownFileTypes = true;
        options.DefaultFilesOptions.DefaultFileNames = new[] {"index.html"};
        app.UseFileServer(options);

        app.Map("/api", api=>{
            api.UseOwin(x => x.UseNancy());
        });            
    }
}

Now, if you launch the web server with dnx kestrel or Cmd-Shift-P kestrel, you should be able to navigate to http://localhost:5000 to view the static index.html and http://localhost:5000/api to see the “Hello World” from the HomeModule.

This is a great place to stop. You can now either set up AngularJS, React or Aurelia in the wwwroot folder.

References

Advertisements

Hitting the Product Sweet Spot

Getting a product out the door requires a tremendous amount of time, money and effort. There’s nothing worse than going through all that and then have little to no market adoption.

Unfortunately, there is no crystal ball when it comes to getting your product right. But there are a number of strategies at your disposal.

Imagine you are standing in a room where the other end of the room is pitch dark. Now also imagine there is a dartboard somewhere in the dark part of the room. This is a simple analogy to building products and hitting the illusive market bullseye. Each dart is costly. What are your options?

You could build one dart and hope to get lucky. Or, rather than building one expensive dart (I suppose darts have different aerodynamic properties based on shape and materials used), you could build a whole bunch of low cost darts and hope one of them hits the sweet spot.

You could do market research, but that’s like asking people who’ve wandered about in the darkness where they think the dartboard is.

Alternatively, you could do what the Lean Startup movement is all about: You build several low cost darts that have a light on each. And each time it lands in the dark side of the room, it illuminates a part of the wall so within a few darts, you can see the dartboard. If you’re having trouble with this analogy, the light on the dart is what user data analytics is all about and Google and many other companies take this approach.

Lastly, you could do what Apple does. You turn off the lights in your side of the room, drop some acid, put on some Dylan and wait till your eyes adjust to the darkness and are able to see the outline of the dartboard :). Few companies have mastered being able to see into the dark like Apple has.

My Core Coding Principles

Over the years, I have worked on and lead several development teams. The following core principles have helped guide me.

  1. Prime directive:  Let no one have cause to alter your code
  2. When meeting your manager/team lead/peer, be as prepared to tell them what you should be working on as they are
  3. If you spot bad or faulty code, find the person responsible and have them fix it or fix it yourself. Never scroll past bad code and think it’s someone else’s problem
  4. It doesn’t matter if some other part of the program is broken – if it’s broken, your product is broken and you are at cause. Take it personally
  5. Do not let your code cause other people’s code to break. Test, document and communicate
  6. Do not write code that, when you come back to months later, requires you to have to re-learn your thought process. Make your code self-evident. Otherwise, document/comment in detail
  7. Pay attention to what my change above or below your code in the architecture stack and code defensively – wherever possible, have code break at compile time instead of runtime
  8. Quality of code beats quantity of code any day. Bugs are a bigger measure of your skill level than late delivery
  9. If you have a gut feel that what you are coding is not good code/design. Stop and ask for a second opinion from a peer. Talk it out – never rush to completion
  10. Take effort to make your team aware of what areas of the product you are working on and what outcomes they can expect from your work instead of simply reporting timesheets
  11. Always be learning – share cool new concepts that you come across
  12. Take ownership of the product’s success even if someone else’s way of doing things prevails. It is after all, the sum of all our efforts

I hope they serve you as well. You may also wish to write down your own and share them with your team. Nothing is static in our ever changing field. I intend to review and update these from time to time.

Southern Straits 2011 – Kiva

Easter 2011 meant that it was time for the Southern Straits Regatta again.  After last year’s crazy ride, we were prepared for the worst, however; the weather this time around was polar opposite.

As always, we started just off Dundarave Pier in West Vancouver where a small crowd of well wishers had gathered to send us off. The 90 nautical mile course first took us out to the Ballenas Islands, then to Entrance Island, Halibut Bank, back to Entrance before the final finish at Point Atkinson Lighthouse. We expected the race to last 30+ hours so the plan was to have the 10 person crew work in 4hr shifts. But given the beautiful sunshine and calm steady winds, after an entire week of rain, no one really wanted to hang out down below. We were in great spirits and recanted war stories of previous sails as we beat up the south side of Bowen. We stayed out of the Strait as it looked like the best winds were along the coast.

Thanks to Jill and Layne, the crew enjoyed a delicious dinner of beef bourguignon which we re-heated in the oven as we watched a beautiful sunset. At 8 o’clock, we started our shifts as half the crew went down below to some scotch and some sleep. As darkness enveloped us, we made the dash across the Strait to Ballenas. I’m uncertain of the exact point along the coast that we cut across as our Spot tracker was not working. As a result, we don’t have a GPS track of the route we took. The temperature plunged to near zero Celsius but thankfully, we had warm clothing. On the positive side, we were able to stream Radio Horyzont.pl over 3G with my Galaxy Tab. We live in amazing times when one can stream music from a radio station from Poland over the internet to a sailboat in the middle of the Georgia Strait. We came up to Ballenas at midnight, just in time for crew change. We’d picked up speed and were now doing about 7kts. The rest of our crew shook off their sleep and we had all hands on deck for the kite hoist and rounding.

One doesn’t really sleep while underway during a race – at least I didn’t think I did, though the rest of the crew assures me otherwise. I faded in an out to the sounds of water splashing against the hull and the occasional sounds of laughter from the cockpit and grinding winches. My body was exhausted but my mind was too excited to sleep. I kept waking up whenever the voices picked up in the cockpit, trying to stay with whatever was going on in the race and alert in case there was a call for all hands on deck.

My shift started at 4am as we just rounded Entrance Island. Words cannot describe how surreal it is to look back into the darkness and see four spinnakers barrelling down upon you as you leave a wake glimmering with phosphorescence.   These guys meant business and we went from sleep to race mode, anxious to keep our lead. It took us 4 hours to get to Halibut Bank, round the mark and get back to Entrance Island. When the relief crew came back on deck, it seemed to them that we had not moved at all. Joking aside, we are on the final leg of the race and no one could sleep. Sunrise had brought another gorgeous day but the winds were getting lighter and we had come too far to be dead in the water. After a breakfast of porridge and coffee, we decided to take the rhumb line to Pt. Atkinson as some of us cracked open a beer and prayed – thankfully, the wind held steady. While light at times, we never really hit 0kts at any point during the race.

Kiva crossed the finish line at exactly 1pm putting our course time at almost 26.5hrs. Finishing is an exhilarating experience and gives one a huge sense of accomplishment. Finishing with a a great crew is just that much sweeter. Some races you fight the weather gods wrath, and others, the weather gods deliver you the only two days of beautiful sunshine amidst weeks of rain. Kiva will be racing in the Swiftsure Regatta on May 27/28 and will then do the 2 week Van Isle 360. We would all like to thank our crew mate Izzie Egan for the video footage from the race.

42nd Southern Straits Regatta on Kiva

Kiva - Southern Straights I did the Southern Straits 2010 Regatta on Kiva, a Finngulf 41 skippered by Julien Sellgren this past Easter Weekend. The regatta, organized by the West Vancouver Yacht Club, was to be my first overnight endurance race. The race started near Dundarave Pier in West Vancouver and the 87 mile medium course would take us into the Straits, off the coast of Nanaimo. At an average speed of 5kts, I expected to be out for anywhere from 17-24hrs. We had organized ourselves into two shifts however, I didn’t really expect to get any sleep.

I checked the weather forecast at 5am on Easter Friday (race day) and Environment Canada had a gale warning in effect for the Straits. Winds were expected to gust up to 40kts easing to 20kts by 2pm that afternoon. We’d experienced 25-30kt winds under full sails on a weekend trip to Gibsons a few months back and Kiva and the crew handled it very well. I’ve only been racing for a year now but had grown somewhat accustomed to high winds at the start of the racing easing off as the day progressed. This was typically in line with predictions by various weather services and I didn’t expect any different this time.

A small crowd had gathered at the pier to see the race start. Winds were at 20kts when we started off heading south west towards the Gulf Islands. We held off on flying our spinnaker while we assessed the situation. Two boats put theirs up and within minutes, one of them was torn to shreds – overpowered by the high winds. The second one didn’t last much longer. Holding off on the kite meant that I was done for now as I was on kite flying duty. We saw one boat round up in the distance but we were able to hold our own. By the time we got to UBC, we were in 2nd place however, it was still just the beginning of a long race.

As we got into deeper waters, the winds had picked up past 30kts and the sea was visibly rougher. We rounded up a couple of times however, quickly came up with a rhythm of calling out the wind gusts and bearing away just in time to keep control. After about an hour of this, it seemed like we had things well in hand and that we could wait out the gale. After all, the forecast was for winds to ease at around 2pm. Watching other boats wipe out was gut wrenching for me – I couldn’t help but empathize with the crews out there. Given my limited rough weather experience, I was getting a crash course on how boats handle when overpowered.

We checked our watches and it was now 1pm. We’d been racing for just over 2hrs. Something was not right, instead of the weather easing, it was getting stronger. Winds were now inching up to 40kts and when we managed to surf a wave, Kiva saw bursts of speeds close to 15kts. The waves were getting more erratic and were building. Without any clear reference point, it was hard to figure out how high the waves were however, on one occasion, it felt like I was peering over the edge of a second storey balcony. We got overpowered and rounded up a couple more times and each time, it seemed to take a bit longer to get back on course. But each time, my crew mates skilfully brought Kiva back on course. And then, all hell broke lose…

We were once again rounding up when I saw a rush of water coming at me. I yelled out “wave” and braced for impact as water rushed over the me and submerged the cockpit. When I managed to pop my head up, I saw a tangle of boots and jackets on the low end of the boat. The cockpit looked like a hot tub and I could see sandwiches and drink bottles floating away out to sea. As the water drained out, we saw that one of our crew had gone overboard. Thankfully, we were all tethered in. I held on to the high side as crew close by rushed to pull him back in. Our skipper called to drop sails and powered up the engine – we were done racing. Our priority now was to fend of hypothermia. As I struggled to release the jib halyard, the boat heeled violently onto port and another crewmember trying to lower the main sail went overboard. I ran up to foredeck to help him aboard. Just as he climbed aboard, I saw the jib rip out of its track and fall into the ocean. Thankfully, between that and the main sail coming down, we no longer had the full force of the wind upon us. Just as we managed to get the ship under control, we saw a boat in the far distance lose its mast. Once we were able to ascertain that they had the situation under control, we made for Nanaimo and safe harbour.

It took us about 2hrs to motor out to Nanaimo as the storm continued to surge. Once docked, my crew mates and I took stock of the boat and began reporting damages only to be waved off by the skipper. “We’re all safe and no one’s hurt and that’s all that matters…” is all he said as he cracked open a bottle of rum. We listened to the rest of the carnage on channel 16 as boats radioed the coast guard, eager for news about friends and loved ones. We heard of one sinking and two boats dismasted as we rendered assistance to boats coming in.

There’s been lots of coverage on whether the race should have gone ahead and no doubt, it was a rough day for the coast guard (not to mention those who waited for them in frigid waters for well over an hour). I’m told there was a total of 36 calls into them for assistance. The weather is very hard to predict and I don’t believe anyone rightfully expected winds building past 40kts let alone 60kts as was finally the case. A lot of the news coverage has the benefit of hindsight and I don’t believe that any skipper would knowingly put their rig and crew in harms way. Same goes for the race organizers. I’m sure there will be a lot of talk about this race in the community and as a rookie, I got to learn from having been there. The coast guard did however knowingly put themselves in harms way to rescue those in need – for that, I’m certain the sailing community is forever grateful. I for one am very thankful to have been on Kiva, serving with the crew I had and having everyone in the race return safe.

If you’d like a more colourful account of the race, here’s one by Peter Lagergren (Strait Jackets) and another one here.

Saving a Silverlight RIA (or WCF RIA) filtered result set

Silverlight RIA (now WCF RIA) services allows developers to create n-tier applications on top of ASP.Net. There are numerous videos and articles on this new technology. This article assumes you know all about RIA Services, DomainDataSources and how FilterDescriptors can be used with ControlParameters to query data from the server side.

I recently needed to save the filtered result set and didn’t find this to be straight forward. I did come up with the solution described here.

Let’s assume you have a simple Contacts database and the user is able to filter by FirstName, LastName etc. Now let’s assume you need to be able to save the filtered result-set (or alternatively bulk modify the filtered result-set). The challenge is to retrieve the Contact id’s with the client side filters applied.

If we were to implement a save function as follows:

IQueryable SaveContacts()
{
    var query = from contact in
                Context.Contacts select contact.Id

    // use the id's in query
}

This would return all the contacts in the database and not the filtered set. Thankfully, the DomainService class implements a virtual function where we can intercept the client side filter expression:

public virtual IEnumerable Query(QueryDescription queryDescription, out int
totalCount);

We however have to merge this expression with the Context.Contacts IQueryable. This didn’t prove to be straight forward as you have to know a little bit about Expressions. I overrode the function like so to save the query for later retrieval:

IQueryable savedQuery;

public override System.Collections.IEnumerable Query(QueryDescription queryDescription,
                                                      out int totalCount)
{
    if (queryDescription.Method.Name == "SaveContacts")
	savedQuery = queryDescription.Query as IQueryable;

    return base.Query(queryDescription, out totalCount);
}

We now have the query expression which contains the “Where” clause generated by the client side FilterDescriptors. We have to merge this query expression into the Context.Contacts query to get the filtered query. The following implementation of SaveContacts demonstrates how to accomplish this:

// The FindWhereMedhod recursively looks for the "Where" clause in the query
// expression
MethodCallExpression FindWhereMethod(MethodCallExpression expression)
{
    if (expression == null)
        return null;

    if (expression.Method.Name == "Where")
        return expression;

    foreach(Expression sub in expression.Arguments)
    {
        MethodCallExpression result = FindWhereMethod(sub as MethodCallExpression);
        if (result != null)
            return result;
    }
    return null;
}

public IQueryable SaveContacts()
{
    IQueryable q = GetContacts();

    MethodCallExpression method = savedQuery.Expression as MethodCallExpression;
    MethodCallExpression whereMethod = FindWhereMethod(method);

    IQueryable contactIds;

    if (whereMethod != null)
    {
        ParameterExpression pe = Expression.Parameter(typeof(Contact), "contact");
        UnaryExpression unaryExpr = whereMethod.Arguments[1] as UnaryExpression;
        MethodCallExpression whereCallExpression = Expression.Call( typeof(Queryable),
                                                                    "Where",
                                                                    new Type[] { q.ElementType },
                                                                    q.Expression, unaryExpr.Operand);
        IQueryable merged = q.Provider.CreateQuery(whereCallExpression) as IQueryable;

        contactIds = from c in merged
                    select c.Id;
    }
    else
    {
        contactIds = from c in q
                     select c.Id;
    }
    // You now have a query merged with the client side contact id's. You can now do
    // whatever you'd like with the contact id's including save them via SqlCommands

    DbCommand command = Context.GetCommand(contactIds);
    string connectionStr = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;

    using (TransactionScope scope = new TransactionScope())
    using (SqlConnection connection = new SqlConnection(connectionStr))
    {
        connection.Open();
        try
        {
            // There are other queries here that necessitate the transaction scope however,
            // these have been removed for simplicity

            string insertCmd = "insert into ContactResultSet (ContactId) select Id from ({0}) as subQuery";
            insertCmd = string.Format(insertCmd, command.CommandText);
            SqlCommand cmd = new SqlCommand(insertCmd, connection);

            // We have to copy over the parameters
            foreach (SqlParameter param in command.Parameters)
                cmd.Parameters.AddWithValue(param.ParameterName, param.Value);

            cmd.ExecuteNonQuery();
            scope.Complete();
        }
        finally
        {
            connection.Close();
        }
    }
}

Round Bowen Regatta – Arashi, Toybox

Round Bowen Start

I had the pleasure to do the Round Bowen 2009 Regatta on Arashi. To get there, I took Toybox out for a nice three day weekend on my first crossing of the Georgia Straight. I had a great crew and we sailed all the way from just past the Burrard Bridge to Passage Island.

It was a beautiful race day and we were fortunate to have wonderful winds for the entire circumnavigation. As usual, the Arashi crew were in high spirits. Various friends came out on the Granville Island water taxi or on the BC Ferries to join in the festivities.

You can see pictures of the long weekend here.