Jon Galloway

ASUS Zenbook UX31 - First Look

I've been through several laptops over the years, three in the past two years. I had an old Dell beater as a fallback, but for a while my main laptop was a Dell Latitude XT2. The XT2 seemed promising - a small laptop with a touch screen - but poor drivers and slow performance made it barely usable. It was bad enough trying to do day to day work on it, but when I used it to give technical presentations it was flat out embarrassing. That's why, when I was up for a new work laptop, I jumped at the Lenovo W520. The W520 is an enormous brute of a machine in every sense - literally more powerful than most desktop machines, and not much smaller. That's fine, I thought - I'll happily trade convenience for a machine that actually works.

I tell you that history to explain why, when I was offered the opportunity to review an Intel Ultrabook, I was pretty skeptical. I reviewed some of the different options available and - while they looked good - I didn't expect a lot in the way of power, especially when I saw that the prices were pretty reasonable.

As I said, I was offered an Ultrabook in exchange for a review, so here's the disclaimer: I received an ASUS Zenbook 31 for free in the hope that I would mention it on my blog. Regardless, I only recommend things I personally endorse and would recommend. I'm disclosing this in accordance with the FTC's Guides Concerning the Use of Endorsements and Testimonials in Advertising. Just in case, I also cleared it with my employer's legal / corporate affairs team. I also made sure the agreement said that my review would be my honest opinion, and that's what this is. This is my opinion alone, and doesn't necessarily reflect the views of my employer.</disclaimer>

The offer was to review an Ultrabook from Intel's current lineup, so step one for me was to compare the options. There are a lot of good choices out there, and while I was interested in the Lenovo U300s (a pretty gorgeous machine) I kept coming back to the ASUS Zenbook. It stood out for a number of reasons, but one big one was the screen resolution. Just about every comparable laptop out there maxes out at a screen resolution of 1366x768 or 1440x900 (including the top MacBook Airs), the Zenbook UX31 goes all the way up to 1600x900. Based on recent history with trying to work and give technical presentations using small laptops, I wasn't interested in reviewing anything I couldn't do real work and consider presenting with. If you're looking for an ultrabook form factor laptop to do real work on (as opposed to web and media) I think those extra pixels are a big deal.

Unboxing

This laptop was very well packaged. It was obvious from the start that attention had been paid to quality and elegance, and I think it works. This felt like unpacking a quality consumer product, not your typical laptop box full of random papers and promotional CD-ROMS.

IMG_6172

After removing the small but solid Zenbook, I found a sturdy looking carrying case. As others have noted, a carrying case for this seemingly indestructible laptop seems like overkill, but it sure looks nice.

IMG_6173

After removing the Zenbook and the case (pictured later), you find a nice introductory card on top of a small box with other necessary but not beautiful stuff (owner's manual, warranty card, etc.). Again, opening this laptop feels like an experience.

IMG_6174

So at the risk of being incredibly nitpicky here, I found it odd that the Zenbook card was completely devoted to talking about features of the Zenbook, and none said anything like "You'll need to plug in your Zenbook before using it." Yes, I'm a computer guy who knows (expects) that laptop batteries won't stay charged during shipping and the dang thing needs to be plugged in when you open the package, but I'm thinking like a non-techy consumer who's buying a consumer electronic gizmo here. When I take the Zenbook out of the box and try to turn it on, nothing happens. The welcome card should cover that.

On to the actual laptop - the Zenbook!

IMG_6177

This is a good looking, solid machine. It's small but heavy. When I showed it to my 7yo daughter and asked what she thought it looked like, she said, "Expensive!" I agree, and while this doesn't come through in a blog post, the laptop itself feels very substantial. It's not heavy, but it feels hefty for its petite size.

The case is solidly constructed and looks nice.

IMG_6220

A Few (Minor) Complaints about the First Run Experience

For such a beautiful unboxing experience, I had (unrealistic?) expectations for the first run experience. Things went downhill a little bit when I turned the Zenbook on. The first prompt I got required me to accept an agreement to install the Bing Bar.

IMG_6183

What was especially frustrating with this prompt was that there was no choice - in order to start the machine up, I needed to agree to the Bing Bar license - the Next button is disabled until I do. That really broke the "fancy" feeling. Things continued in that direction after the installation completed, with a bunch of annoying dialogs:

Desktop -2

Look, I get that crapware manufacturers pay computer manufacturers money to bundle trial software, and that (kind of) benefits consumers by lowering prices. That's the real world. I think this could be done better, though. Either charge a bit more and ship a beautiful first run experience, or at least bundle all the lame crapware dialogs into one. The overlapping, uncoordinated dialogs feel cheap cheap cheap, which ruins an up-til-then beautiful experience. It's something I expect in a budget laptop, but not something as beautiful (and as beautifully packaged) as the Zenbook.

Curious, I took a quick look at the pre-installed goodies, and wasn't surprised to see quite a list:

2012-01-25 01h13_20

So, I could (and will) uninstall the junkware, but was a little disappointed to see it as a part of an otherwise beautiful setup install experience. I don't want to give the wrong impression here - these are minor annoyances, and don't really significantly detract from the actual use of this beautiful machine after the first few minutes. It's just that they've obviously invested a lot of effort in packaging, and it's a shame to see that emotional appeal damaged even in the slightest when I turn the machine on.

Fast

Regardless of any unwanted pre-installed goodies, this thing is snappy right out of the box. Without installing any updates or uninstalling anything, I got a 5.6 WEI.

2012-01-25 10h09_42

These are pretty fast scores. And, more important, so far this thing feels fast. I've been using it for a week and this thing just feels fast all the time.

Face Login

Okay, I'll talk more about this machine once I've used it for a few weeks, but I wanted to show off one cool feature - Face Login. The webcam locks in on you face and automatically logs you in, as shown below.

I've used a few webcam login systems, but none of them have worked near this well. The Face Login system really works - it's fast and it's fun.

Summary

So far I'm very impressed. While this post focuses on the first few hours with the laptop, the reality is that what's really important is all the hours that follow. I'll write I more detail once I've used this more, but this past week has shown me that this is an amazing laptop. If I was shopping for a new laptop today and my friend showed me this machine, I'd buy it... and I'm a hard sell.

Some more links for the Zenbook UX31:

Posted by Jon Galloway | 8 comment(s)
Filed under:

10 Things ASP.NET Developers Should Know About Web.config Inheritance and Overrides

The ASP.NET configuration system is build around the idea of inheritance:

Each Web.config file applies configuration settings to the directory that it is in and to all of the child directories below it. Settings in child directories can optionally override or modify settings that are specified in parent directories. Configuration settings in a Web.config file can optionally be applied to individual files or subdirectories by specifying a path in a location element.

The root of the ASP.NET configuration hierarchy is the systemroot\Microsoft.NET\Framework\versionNumber\CONFIG\Web.config file, which includes settings that apply to all ASP.NET applications that run a specific version of the .NET Framework. Because each ASP.NET application inherits default configuration settings from the root Web.config file, you need to create Web.config files only for settings that override the default settings.

For a lot of sites, you don't really need to know about that - you can get by with one Web.config file for the site. But, knowing how the inheritance works - and how to control it - can really help out.

I've noticed that a lot of the questions I answer questions on forums, StackOverflow, and internal e-mail lists can be solved by better understanding how ASP.NET configuration inheritance and overrides work. And so, a bunch of tips about how ASP.NET configuration inheritance and overrides work! I'll start with some basics, but there are some towards the end I'll bet most ASP.NET developers don't know.

Tip 1: Using Web.config files in site subfolders

And ASP.NET website's Web.config is part of an inheritance chain. Your website's subfolders can have Web.config - an example is the Web.config file in an ASP.NET MVC application's View folder which does things like preventing directly viewing the View templates:

2012-01-12 23h57_09

This allows for setting general settings at the site level and overriding them when necessary. Any settings in the base Web.config that aren't overridden in the subfolder stay in effect, so the "child" Web.config can be pretty small. You can continue to nest them, so sub-sub-subfolders can get their own Web.config if needed. Some of the most common uses of subfolders are to restrict permission (e.g. requiring authentication or restricting access to resources), but you can also use them to do things like include default namespaces in Views, toggle handlers, etc.

Tip 2: Understand how your site Web.config inherits its settings

But there's an inheritance chain above the site, too. Here's a simplified version from the MSDN docs:

Configuration level

File name

File description

Server

Machine.config

The Machine.config file contains the ASP.NET schema for all of the Web applications on the server. This file is at the top of the configuration merge hierarchy.

IIS

ApplicationHost.config

ApplicationHost.config is the root file of the IIS 7.0 configuration system. It includes definitions of all sites, applications, virtual directories, and application pools, as well as global defaults for the Web server settings. It is in the following location:

%windir%\system32\inetsrv\config

Root Web

Web.config

The Web.config file for the server is stored in the same directory as the Machine.config file and contains default values for most of the system.web configuration sections. At run time, this file is merged second from the top in the configuration hierarchy.

Web site

Web.config

The Web.config file for a specific Web site contains settings that apply to the Web site and inherit downward through all of the ASP.NET applications and subdirectories of the site.

ASP.NET application root directory

Web.config

The Web.config file for a specific ASP.NET application is located in the root directory of the application and contains settings that apply to the Web application and inherit downward through all of the subdirectories in its branch.

ASP.NET application subdirectory

Web.config

The Web.config file for an application subdirectory contains settings that apply to this subdirectory and inherit downward through all of the subdirectories in its branch.

So your website's configuration's actually inherited a bunch of settings that were set at the server level. That's nice for a few reasons:

  1. It allows the ASP.NET / IIS teams to migrate settings that aren't commonly modified from the project template Web.config files to server defaults, keeping your Web.config files smaller and more readable. For example, ASP.NET 4 migrated a bunch of handler registrations to Machine.config, so the Empty ASP.NET Application Web.config is slimmed down to about 8 lines.
  2. You can override things at the server level as needed, and they'll take effect for all applications. For example, you can set <deployment retail="true"> on production servers to disable trace output and debug capabilities.
  3. You can find a lot of useful information in the Machine.config default settings since they're stored in plain text. For example, the ASP.NET Membership Provider has some defaults set for password requirements and the membership database, and you can look them up by looking in the appropriate .NET framework version's Machine.config. For a default installation of ASP.NET 4, that's found in C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config with a quick search for <membership>.

Tip 3: Understand how your Web.config inherits IIS configuration settings

This overlaps a bit of Tip 2, but it bears repeating. Long-time ASP.NET developers (myself included) are prone to thinking of ASP.NET and IIS configuration separately, but that all changed with IIS 7. This is all pretty old news, as IIS 7 has been out for a while, but it hasn't been completely absorbed by ASP.NET developers.

CarlosAg summed this up well in a post from 2006(!) which explained The New Configuration System in IIS 7.  I'm not going to rehash his post here - go read it. Some important takeaways are that both the ApplicationHost.config and Machine.config feed into the configuration settings in your site's Web.config, as shown in Carlos' diagram:

In addition to the understanding how things work part of it, this is also good to know because - based on the info in Tip 2 - you can see what the base settings are, and how you can override them in your application's Web.config. This is why you can do pretty advanced things like configure rules on for the URL Rewrite Module in your application's web.config.

Of course, server administrators don't necessarily want to allow any application on the server to modify settings via Web.config, so there are configurable policies in the ApplicationHost.config which state whether individual applications can override settings. There's also an Administration.config file which controls things like Module registration.

There's one kind of new update to this list - using aspnet.config for Application Pool tuning. It's found in the same directory as Machine.config, and it's been around since .NET 2.0. However, as of ASP.NET 4 it's been expanded to handle things like concurrency and threading, as explained in Scott Forsyth's post, Setting an aspnet.config File per Application Pool. While not something most ASP.NET developers will need to use, it's good to know that you can control things like maxConcurrentRequestsPerCPU, maxConcurrentThreadsPerCPU and requestQueueLimit at the application pool level.

Tip 4: Location, location

While it's nice to be able to override settings in a subfolder using nested Web.config files, that can become hard to manage. In a large application, it can be difficult to manage settings because you can't see the effective permissions in one place. Another option is to use the <location> element to target settings to a specific location. For example, I previously showed how to use this to allow large file uploads to a specific directory in an ASP.NET application using the location element:

<location path="Upload">
    <system.web>

        <httpRuntime executionTimeout="110" 
                     maxRequestLength="20000" />
    </system.web>
</location>

Tip 5: Clearing parent settings when adding to a collection

Sometimes you want to remove all inherited settings and start fresh. A common place you'll see this is in handler, module, connection string and provider registration - places where configuration is used to populate a collection. Scott Guthrie blogged about an example in which just adding a new Membership Provider causes problems, because you end up with two providers - the default, and the one you just added. It's important to clear the collection before adding your new provider using the <clear/> element, like this:

<membership>
      <providers>
          <clear/>
          <add name="AspNetSqlMembershipProvider"
              type="System.Web.Security.SqlMembershipProvider, 
                    System.Web, Version=2.0.0.0, 
                    Culture=neutral, 
                    PublicKeyToken=b03f5f7f11d50a3a"
              connectionStringName="MyDatabase"
              enablePasswordRetrieval="false"
              (additional elements removed for brevity)
          />
      </providers>
</membership> 

As Scott explains, failure to <clear/> the collection first results in both providers attempting to handle membership, which probably isn't what you intended.

Tip 6: Locking settings with with allowOverride and inheritInChildApplications

You may need to prevent sub-applications from overriding or extending settings. You can do that with the allowOverride attribute, which does exactly what the name suggests - the same way a sealed class prevents changes via a derived class. The MSDN documentation summarizes this well:

You can lock configuration settings in ASP.NET configuration files (Web.config files) by adding an allowOverride attribute to a location element and setting the allowOverride attribute to false. Then within the location element, you can define the configuration section that you want to lock. ASP.NET will throw an exception if another configuration file attempts to override any configuration section that is defined within this locked location element.

Using a location element with an allowOverride=false attribute locks the entire configuration section. You can also lock individual configuration elements and attributes using lockItem, lockElements, lockAttributes, lockAllAttributesExcept, and lockAllElementsExcept.

That last part there - using attributes on sections - works because those lock attributes are among the general attributes inherited by section elements.

Tip 7: Disinheriting your child applications with inheritInChildApplications="false"

If you've got settings that should only apply to the parent application and shouldn't be inherited, you can use the inheritInChildApplications attribute on any section or location element. That makes the settings at the current level, but inheriting applications and subfolders don't have to bother with clearing and rebuilding configuration just to remove those settings.

This came up in a recent question on StackOverflow:  Unloading parts of a web.config file from a child application

Since Web.config is so heavily built on the concept of inheritance, it's not surprising that turning it off for a section can have some side effects. The aptly self-named "Run Things Proper Harry," a.k.a. rtpHarry, has written up two good posts covering usage and important things to be aware of.

Tip 8: Use configSource to separate configuration into separate files

While I've been discussing modification of Web.config settngs through inheritance, it only makes sense to mentions some useful ways to handle overriding Web.config settings.

Any Web.config section can be moved to a separate file by setting the configSource attribute to a file reference. I've mostly used this for handling connection strings, since it allows you a lot more flexibility over versioning and and deployment. Instead of having different Web.config files for each environment ("Oops! Just deployed the staging Web.config to production!!!"). It looks like this:

<configuration>
  <connectionStrings configSource="connectionStrings.config" />
  ...

Then your connectionStrings.config file only needs to change between environments, and can contain specific settings. It holds the contents of the element you're referring to, so it looks like this:

<connectionStrings>
  <add name="subtextData"
    connectionString="Server=.;Database=staging;Trusted_Connection=True;" />
</connectionStrings>

Another way I've seen this done is to have differently named connection strings config files for each environment (e.g. dev.config, staging.config, production.config). That allows you to check them all in to source control and not worry about getting files with the same name but different contents mixed up, but the tradeoff is that your Web.config in each environment needs to be updated to point to the right config source.

So, this is a handy trick, but isn't quite perfect. A better option is to use Web.config File Transformations.

Tip 9: Use Web.config Transforms to handle environmental differences

I don't hear as much about Web.config Transforms as I'd expect. Maybe they just work and everyone just quietly uses them and doesn't talk about it. But from the questions I see coming up over and over again, I'm not sure that's the case.

I love Web.config Transforms. At my first ASP.NET MVP summit, I was part of a feedback group discussing frustrations with deploying ASP.NET applications. Two themes that came up over and over were difficulties with packaging and managing configuration. That team later produced Web Deployment Packages (a nice format that packages files and settings for a site in a way that can be inspected and modified during installation) and Web.config Transforms.

All the new ASP.NET projects have Web.config transforms already set up - if you expand the Web.config node, you'll see that it's configured to create different settings for Debug and Release mode.

2012-01-17 14h51_29

It's really easy to use - your main Web.config has the base settings for your site, and whenever you build, the transforms for the appropriate build configuration (e.g. Debug or Release) are automatically applied. If you had a Test database that you wanted to use by default, but wanted your Release builds to run against the Production database, you could set it up so that your base Web.config connection string points to the Test Database connection string, like this:

<connectionStrings>
  <add name="ApplicationServices"
      connectionString="[TestDatabase]" />
</connectionStrings>

Then your Web.Release.config overwrites that to point at the Production database, like this:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add name="ApplicationServices" 
        connectionString="[ProductionDatabase]" 
        xdt:Transform="Replace" xdt:Locator="Match(name)"/>
  </connectionStrings>
</configuration>

The syntax is pretty straightforward, but you don't need to worry about that because the comments in the Web.Release.config file already show how to do that.

To be clear: unlike the other examples, this is something that happens at build time, not runtime.

I recently ran into an issue where I wanted to deploy something to AppHarbor and wanted to switch between a local SQL Compact database and the hosted database server, and Web.config Transforms worked just great there.

There's a lot more to talk about with Web.config Transforms that's beyond the scope here, such as:

  • You can create as many build configurations as you want, with different transforms for each configuration. This makes it simple to switch between different settings in your development environment - say, switching between several development databases or other application settings.
  • You can use the configuration transformation system with any XML file using the SlowCheetah Visual Studio extension. Scott Hanselman's written a post with more information on that here: SlowCheetah - Web.config Transformation Syntax now generalized for any XML configuration file
  • Sayed (the Microsoft developer who's worked on both Web.config Transforms and the SlowCheetah extension) has also built a Package Once Publish Anywhere NuGet package which allows you to defer running the transforms until later, using a PowerShell command. That means you can build one Web Deployment Package with all the transforms included, and run them when you're going to deploy to a specific environment.

There's some good information on MSDN about Web.config Transforms:

Tip 10: Managing Application Restarts on Configuration Changes

There are a lot of moving parts in figuring out the configuration for a website, as illustrated above. For that reason, ASP.NET computes the effective settings for the site and caches them. It only recomputes them (and restarts the application) when a file in the sites configuration hierarchy is modified. You can control that on a section by section level using the restartOnExternalChanges property.

One place where configuration changes don't automatically get recomputed is for external config files set using configSource (as shown in Tip 8). You can control that by setting restartOExternalChanges="true" for that section. There's an example on MSDN that shows this in more detail by creating an external configuration file which is loaded via the configuration API (not referenced via configSource), then toggling the restartOnExternalChanges property and showing the differences in operation.

Summary

The ASP.NET Configuration system does quite a bit - I didn't even mention big topics like using the API for reading and writing values to both local and external config files or creating custom configuration sections. This post focuses on one aspect: getting things done by understanding and leveraging inheritance and overrides. Hopefully this gives you both some new tools for effectively handling configuration and some background that helps in troubleshooting when configuration is working as you'd like.

Are there any essential tips that I missed?

Posted by Jon Galloway | 25 comment(s)
Filed under:

Excerpt Old Posts - A WordPress Plugin to get around the Feedburner 512K Limit

Summary

If you've got a WordPress blog and use Feedburner, you may notice that the posts stop updating. It's often due to a limitation on Feedburner that stops updating if your feed exceeds 512K. I wrote a simple plugin called Excerpt Old Posts that fixes that problem by showing Full Text for recent posts and Summary for older posts.

Background

I run a podcast website (Herding Code podcast) on WordPress. The feed's probably the most important part of that site, since it's how people subscribe, feeds into iTunes and other podcast directories, etc. We put some work into the show notes, so I definitely want full text for each post in the feed. For users who just find the podcast, I want them to be able to find all our episodes in iTunes or other feed sources. I want a full feed - all text for all the posts.

We use Feedburner for some advanced feed management features, especially

  • Podcast support (it handles all the funky iTunes tags)
  • Tracking and analytics
  • Ability to change hosting without breaking the feed
  • Probably some other stuff I'm forgetting about - I've been using Feedburner for a long time

The Feedburner 512K feed limit

Unfortunately, Feedburner's got a limit of 512K per feed. If you exceed that limit, the feed just stops updating. I've run into this several times - I'd post a new show, and it wouldn't show up in Feedburner. I'd go through the standard Feedburner troubleshooting steps:

  • Manually ping Feedburner to make sure it knew there was something new
  • Check the Feedburner Troubleshootize page, which would lie to me tell me my feed was "quite healthy."
  • Eventually I'd give up and just Resync the feed (the so-called nuclear option)

Finally, when I'd attempt to Resync, Feedburner would tell me what was wrong - the feed was too big: "Feed Error: Your Feed Filesize is Larger than 512K"

There are two problems here:

No compliants on the first problem, Feedburner probably needs to set some limits on feed size or they'd grow like crazy. The big problem is that there's no notification, even in the admin interface, until you try to resync the feed.

My first (lame) solution: Compromise on quantity or quality

If you search around, you'll see that's the common suggestion - go in to to the Reading settings and either change the feed to show a summary for each post, or limit the number of items in the feed.

That solves the problem, but it doesn't make me - or our listeners - happy. As I explained above, everyone wants the Full Text for new content, and new subscribers want to see all shows listed when they subscribe.

What I really want is a feed that has Full Text for most of our newest posts and Summary for our old posts. That lead me to a slightly better solution.

My second (slightly less lame) solution: Hack around in feeds-rss2.php

After a while, decided to dig around and find out where the feed was actually written out. I found that my RSS feed was being written out in feeds-rss2.php, and wrote some ugly but workable code that runs a simple counter and switches from full posts to summaries after the counter hits a threshold. If you need that modified feeds-rss2.php for some reason, it's here. I hope you don't use it, though, because there's a problem: the next time I updated to the newest version of WordPress, my feed broke again.

My third (best) solution: Wrap this logic up in a plugin

Of course, the problem with tweaking internal code is that it gets overwritten when you update. The right way to extend WordPress is to create a plugin. That way your changes are all wrapped up nicely in a way that survives updates. And, also nice, the changes are easy to share with others.

This was my first WordPress plugin, and I'll save that process for another post. The important thing is that the plugin's got the Works On My Machine certification and is up in the WordPress Plugins Directory, titled Excerpt Old Posts. Yes, that's a kind of boring name.

It's pretty easy to use:

Add the Plugin in the WordPress Plugin settings:

In your admin settings, Go to Plugins / Add New. Click on Search and type in "Excerpt Old Posts"

Install the plugin and activate it.

Actually, that's really all you have to do if you want the default number of full posts (50) in your feed. You can check your feed if you'd like - you should now see that the 50 most recent items are showing Full Text, and the older ones are just showing the short Summary.

Changing the number of full posts shown in your feed

There's just one new setting available - the number of Full Text posts you'd like in your feed. Rather than adding a new settings page, I extended the Reading page. It seemed simpler to me - if I end up adding more settings I'll set up a new settings page for the plugin. You can see the new setting below:

WordPress - Excerpt Old Posts

That's it, hope you like it. If you have problems, I'd recommend using the dedicated forum for this plugin rather than the comments on this post, as you're more likely to get a timely response.

Posted by Jon Galloway | 1 comment(s)
Filed under: ,

My wife and I recorded a Christmas song: Twelve Days of the Partridge

Since 2007, my wife and I have been contributing a song to the Familyre Christmas compilation albums. You can download this year's for free, and you can play them all online on Bandcamp. My wife had written original songs each previous year; this year I suggested we just record a classic like The Twelve Days of Christmas.

You can stream or download our song - Twelve Days of the Partridge - here (perhaps while reading this post):

You can stream or download the full album here:

Twelve Days: trickier than you'd think

I originally suggested Twelve Days of Christmas so we could just take it easy this year; I probably should have thought about that a bit first. As an old traditional song, The Twelve Days of Christmas has an interesting song structure. It bounces between 4/4 and 3/4 time, with some pickup notes just to mix things up a bit. It's odd enough that Wikipedia actually has a section talking about the song structure, irregular meter, and other things that give electronic recording people headaches:

The time signature of this song is not constant, unlike most popular music. This irregular meter perhaps speaks for the song's folk origin. The introductory lines, such as "On the twelfth day of Christmas, my true love gave to me", are made up of two 4/4 bars, while most of the lines naming gifts receive one 3/4 bar per gift with the exception of "Five gold(en) rings," which receives two 4/4 bars, "Two turtle doves" getting a 4/4 bar with "And a" on its 4th beat and "Partridge in a pear tree" getting two 4/4 bars of music. In most versions, a 4/4 bar of music immediately follows "Partridge in a pear tree." "On the" is found in that bar on the 4th (pickup) beat for the next verse. The successive bars of 3 for the gifts surrounded by bars of 4 give the song its hallmark "hurried" quality.

The second to fourth verses' melody is different from that of the fifth to twelfth verses. Before the fifth verse (when "five gold(en) rings" is first sung), the melody, using solfege, is "sol re mi fa re" for the fourth to second items, and this same melody is thereafter sung for the twelfth to sixth items. However, the melody for "four colly birds, three French hens, two turtle doves" changes from this point, differing from the way these lines were sung in the opening four verses.

Credits and stuff

My wife Rachel did most of the work on this one: singing, acoustic guitar, ukulele, flute, xylophone.

I played bass, organ, electronic drums (most of which I decided to remove in the mix), and ran most of the recording and mixing. My favorite part was the organ - I used my brother Glen's Nord Electro 2 on a drawbar organ setting with an auto-wah. I love that sound.

We had a bunch of help from our friends:

  • Brian Galloway provided some tasty electronic guitar licks.
  • John Ciccolella hooked us up with some awesome fiddling (and help with the arrangement).
  • Andrew Smith did the work of twelve men (twelve drummers drumming)
  • Our daughters and friends sang the children's choir bit on the 12th day.

Nerdy recording stuff

I decided to do the editing and mixing in Audacity. It's picked up a lot of features over the past few years that really helped, including track groups, envelopes, and solid VST effect support. We ended up with a few dozen live tracks, so there were two main jobs in the mix - fixing little timing issues to tighten it up, and getting the levels right so all the parts were audible.

2011-12-25 11h54_27

Handling timing

With a big song like this, a click track is a must. I also made use of a nice plugin called Regular Interval Labels to visually align audio clips. The big benefit that it provides is that the clips snap to nearest labels a bit, so it's much easier to align them.

Handling volume

For a mix like this, the trick is to make everything audible without clipping. The trap is to avoid saying "Hmm, can't hear the second violin track, better turn it up." Instead, I focus on listening for which tracks can be turned down and still be audible. For a dynamic mix which responds to new instruments joining part way through the song, I really rely on the volume envelopes:

2011-12-25 12h07_46

VST Plugins

I made some electronic drum loops which sounded cool in parts, but it was a pretty busy mix and we ended up pulling most of them out. Rachel and I joked around with putting one halfway through the song, as a brief intermission. It cracked us up, so we decided to keep it. The problem was that it kind of jumped out since it was really punchy, so we ended up thinning it out so it sounded like an old record. We used iZotope Vinyl (free), a classic EQ setting, and dBlue Tape Stop effect (also free). I made the loop in FL Studio Pro - it's intentionally a little out of time so it sounds more natural.

2011-12-25 12h40_33

Last year's track - Glory

If you like this one, you might like the song we did last year:

Merry Christmas!

Working around a Powershell Call Depth Disaster With Trampolines

I just posted about an update to my NuGet package downloader script which included a few fixes, including a fix to handle paging. That sounds boring, but wait until you hear about the trampolines.

Recursion: Seemed like a good idea at the time

The whole idea of this script is to download package files referenced in the public NuGet package feed. The NuGet package is in OData format, and it's paged. That's a good thing - requesting the feed shouldn't make you wait while up to 16,000 (and growing) package descriptions are downloaded, and it shouldn't tie up the server with that either. Each page currently returns 100 items, but that's a service implementation detail that could change at any time.

Paging in OData is done using a <link rel="next" href="http://url.com?$skiptoken=sometoken> element at the end of each page, like this:

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<feed xml:base="http://packages.nuget.org/v1/FeedService.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" 
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Packages</title>
  <id>http://packages.nuget.org/v1/FeedService.svc/Packages</id>
  <updated>2011-12-08T23:46:46Z</updated>
  <link rel="self" title="Packages" href="Packages" />

  <entry>
    <id>http://packages.nuget.org/v1/FeedService.svc/Packages(Id='adjunct-Some.Package',Version='1.0.0.0')</id>
    <title type="text">Some.Package</title>
    <summary type="text">First!!!! w00t!!!</summary>
    < more stuff here />
  </entry>
  <entry>
    < ... entry stuff for another package ... />
  </entry>

  < etc - 98 more entry elements />

  <entry>
    <id>http://packages.nuget.org/v1/FeedService.svc/Packages(Id='adjunct-Last.On.The.Page',Version='1.0.0.0')</id>
    <title type="text">Last.On.The.Page</title>
    <summary type="text">Last package on the first page</summary>
    < more stuff here />
  </entry>
  
  <link rel="next" href="http://packages.nuget.org/v1/FeedService.svc/Packages?$skiptoken='adjunct-Last.On.The.Page','1.0.0.0'" />
</feed>

The important bit is that the link element tells you how to request the next page of information. Here it's a link to the same feed with a skip token indicating the last item we've seen. I'm simplifying this a bit - the feed also handles searching, ordering, etc., but I'm just focusing on the paging bit. If you make a big request, the server returns you a chunk of the results with a link to get the next chunk.

My original implementation was to do something like this:

function DownloadEntries {
 param ([string]$feedUrl) 

    // Download all items on the page
    
    $nextUrl = href from last link on the page
    
    DownloadEntries $nextUrl
}

DownloadEntries $firstPage

Note: If you're new to PowerShell, that's the syntax for writing a function called DownloadEntries which takes a string parameter called feedUrl.

So DownloadEntries gets passed a URL, downloads all entries on that page, and calls itself with the URL to the next page in the list. This works just fine for a while, but the problem is that every page is adding another level to the recursive depth of the call graph, meaning we'll run into trouble soon.

Recursion, Call Stacks, and Stack Overflows

Note: I know I'm going to get #wellactually'd to death. I'm bracing for it. I'm not a Recursion Expert of Recursions, and if you are I'm sure I'll hear about it in the comments. Also, you're a big, mean jerk. Actually, I'm happy to learn more, so fire away. Now with that out of the way...

The most common example of recursion in computer science is when a function calls itself. I first stumbled across it as a junior programmer, when I "re-invented" it to solve a tricky problem. I needed to generate a massive Word document report based on a complex object model, and eventually came up with a function that took a node object, wrote out that node's report information, and called itself for each child node. It worked, and when my boss said, "Hey, nice use of recursion!" I hurried off to read what he was talking about.

Recursion can be really useful, but things can get out of hand. In stack-based languages, recursion requires maintaining the state for everything in the call stack. That means that the memory used by a function grows with the recursion call depth. Since memory is limited, it's easy to write code that will exhaust your available memory, and you'll get a dreaded stack overflow error. Wikipedia lists infinite recursion as the most common cause of stack overflows, but you don't actually have to get all the way to infinity to run out of memory - a lot of recursion is enough.

PowerShell's Call Depth Limit

Rather than wait for a stack overflow to happen - or even for a script to use up an obscene amount of memory - PowerShell caps the call depth at 100. That means that, even if there were no memory overhead to each call, the above function would fail at 100 pages. Doug Finke shows a very easy way to demonstrate this:

function simpleTest ($n)
{
    if($n -ne 0) { $n; simpleTest ($n-1) }
}

PS C:\> simpleTest 10
10
9
8
7
6
5
4
3
2
1

PS C:\> simpletest 99
99
98
97
96
95

The script failed due to call depth overflow. 
The call depth reached 101 and the maximum is 100.

Side Note: PowerShell has the same call depth limit (100) on x64 and x86

Also from Doug's post:

Recursion depth limit is fixed in version 1. Deep recursion was causing problems in 64bit mode because of the way exceptions were being processed. It was causing cascading out-of-memory errors. The net result was that we hard-limited the recursion depth on all platforms to help ensure that scripts would be portable to all platforms.
- Bruce Payette, co-designer of PowerShell

Tail-Recursive Calls and Trampolines

There are ways to work around this problem, but to me they all seem to boil down to replacing deep call stacks with loops - either automatically at the language level or via fancy pants programming. In my case, I needed to convert from recursion to trampoline style - albeit a very simple conversion. With the disclaimer that I'm not an expert here, I thought I'd overview what I read about trampolines, then simplify it down to the basic trampoline solution I ended up with.

Tail Call Optimization

In some cases, languages can optimize their way around this problem. One example is tail call optimization. A tail call is a call which is happening immediately prior to returning from the function, meaning that there's no remaining logic in the calling function and thus no need to retain the stack. In a tail-recursive call, it's returning that value to itself.

Languages can effectively unroll this, since in a tail call situation they don't need to maintain the nested call stack as the calling function has completed all its logical operation. If you're using one of those languages and make sure that your recursive calls are tail-recursive (so no additional logic is performed after the recursive call), the language will handle this for you and you'll end up with the benefits of recursion without the baggage of building a big call stack.

Matthew Podwysocki runs through this in more detail with a comparison of how this works in F# and C# (with an interesting difference between 32 and 64 bit operation). He shows an example of a case where a single line of code after the recursive call breaks the tail call optimization, resulting in a stack overflow.

It's interesting to note that the common language runtime supports tail calls, so it comes down to whether the language and compiler make use of it. PowerShell doesn't support tail call optimization, so I needed to alter my code. That's where I learned about trampolines.

Trampolines

The common pattern I read about for dealing with this is to manage state yourself using a trampoline: a piece of code that repeatedly calls functions. And, depending on the language and recursive requirements, that little "a piece of code that repeatedly calls functions" can get really pretty complex.

If my implementation was really making deep use of recursion in such a way that I really needed to emulate nested calls, that trampoline implementation would need to be pretty sophisticated. While that's implemented differently in different languages, in modern .NET programming I'm reading that's usually done using a function factory trampoline class which calls functions for you. Here are some posts showing how to do that:

In my simple case, though, I could just to convert the recursive call so that it's called from a looping construct, returning state from each call. I'd call this option a strategic retreat, since this is now in no way recursive anymore. But, by calling it a refactoring to implement trampoline-style programming, I'll still keep my pride.

Less Talk, More Code

Right.

So since the reason I was using recursion was just to continue calling the next page after completing the work on the current one, my trampoline can be implemented as a simple for loop into a function that returns the URL of the next page. Remembering that we started with something like this:

function DownloadEntries {
 param ([string]$feedUrl) 

    // Download all items on the page
    
    $nextUrl = href from last link on the page
    
    DownloadEntries $nextUrl
}

DownloadEntries $firstPage

We can rewrite that as this:

function DownloadEntries {
 param ([string]$feedUrl) 

    // Download all items on the page
    
    $nextUrl = href from last link on the page
    
    return $nextUrl
}

while($feedUrl -ne $null) {
    $feedUrl = DownloadEntries $feedUrl
}

This can now handle unlimited pages, since it's just a simple loop. The only downside is that I can no longer feel quite as sophisticated, since while I call that a trampoline, you'd probably call it a boring loop that calls into a function.

Here's the full script so you can see it in context:

NuGet PowerShell Downloader Update - Adding Failed Download Retries, Better Paging Support

I previously posted a NuGet PowerShell downloader script, which is handy for downloading a local NuGet repository. There are several common uses:

  • It's used in corporate environments where network policies prevent developers from accessing NuGet.org
  • It's useful in cases where development teams want to build a customized feed with specific packages
  • It's a great backup for presentations involving NuGet, especially on overloaded conference wi-fi

Note: Now, look, I'm happy if the first two help you out, but that's not what I wrote it for. I wrote this because I was tired of watching speakers at conferences have problems installing NuGet packages and complaining about the slow conference wi-fi. Of course it's slow, it's always slow (it's not lupus, it's never lupus!). If you're doing a presentation that involves you installing a NuGet package, part of your prep needs to be verifying that you have the required packages on your machine.

Matthew Podwysocki recently told me he was getting a call depth overflow error with the script. We looked at it, and it turned out that the problem was that he was downloading significantly more packages than had been available when I first wrote the script. I'd originally tested against several hundred, but there are over 16,000 available now (3,900 unique). I updated the script to fix that, and while I was at it I added in support for retry if a package download fails for some reason. I'll describe the retry mechanism here and save the paging bit for the next post, since that's a bit more in-depth.

Handling Download Retries in PowerShell

Sometimes, downloads fail for any number of reasons. When you're downloading hundreds of files, chances of a failed download go up a bit, and I'd gotten a few requests to handle that better. The dumb-but-working workaround was to just run the script again, since it only downloads packages you don't have locally, but that's not elegant - plus, you might not notice that some of them had failed.

A slightly less dumb workaround is just to retry the download a few times, with a limit to prevent an infinite loop if the file just can't be downloaded (e.g. bad link or missing file). This is pretty easy to implement with a try-catch loop, like this:

[int]$trials = 0
do {
    try {
        $trials +=1
        $webClient.DownloadFile($url, $saveFileName)
        break
    } catch [System.Net.WebException] {
        write-host "Problem downloading $url `tTrial $trials `
                   `n`tException: " $_.Exception.Message
    }
}
while ($trials -lt 3)

The general idea:

  1. Start a counter ($trials)
  2. Increment the counter
  3. Try to download the file
  4. If the download succeeds, break out of the retry loop - we're done here
  5. If we got a WebException, write out a message
  6. If the counter's less than 3, try again. Otherwise, give up.

I was conflicted on the exception handling, but decided that I really only want to retry if I know that the failure was due to a Web Exceptions. If there were an unanticipated DownloadHasSetTheBuildingOnFireException or a BotNetUnleashedSecurityException on the first try, I'd rather not blindly repeat it. Thoughts?

PowerShell 1.0? Forget about that try/catch part.

Try/Catch requires PowerShell 2.0 or later. If you're on PowerShell 1.0, you've got three options:

  1. Just use a trap and don't do retries
  2. Rewrite this to use logic inside the trap block
  3. Use one of the clever solutions out there that simulates try/catch in PowerShell 1.0

If you are on PowerShell 1.0, as is the hapless Matt Podwysocki, you can see what we came up with here.

Converted to a gist

After having made a couple updates to this script and listing it in more than one place, it became obvious that this is exactly what a gist if for. If you haven't seen them, a gist is a single snippet of code that's posted in Github. It can be embedded in a blog post, but more importantly other users can comment on it and fork it, and I can update it. I've updated the original post to reference this gist as well, so if people stumble across the older blog post they'll automatically get the latest, greatest version of this script.

Script and Usage Instructions

I wrote up a walkthrough on the original post; usage hasn't changed with this update.

The paging part is interesting in its own right. We'll talk about that in the next post.

A look back at the ASP.NET site through the years

While writing up the release post for the new ASP.NET website, I started thinking about the site's changed over the years, and that lead me on a brief excursion through the Wayback Machine history of the ASP.NET home page.  Here are some highlights:

Prior to 2001, the site was owned by ASP Computer Products, who appear to have been marketing an External Pocket Print Server for Fast Ethernet. Sadly, I missed my opportunity to go see it at Comdex 2000.

The first ASP.NET related page available is in 2001, and it's pretty much just a splash page.

ASP.NET site - original

By 2002, the site had daily articles, Forums, Tutorials, a Control Gallery, and was advertising Web Matrix - the first one, built to help develop ASP.NET Web Forms.

ASP.NET Site - 2002

2005 saw some big changes in November, for the release of Visual Studio 2005 and ASP.NET 2.0. I fondly remember that release - it was huge! I drove from San Diego to San Francisco to attend an early adopter training week, then spent a good year trying to get my company to buy into updating some of our sites to ASP.NET 2.0.

ASP.NET site - 2005

In 2007, there was an update which brought in the blue color as well as the rounded corners and gradients I was complaining about earlier.

ASP.NET site - 2007

After that, thing didn't change much until March 2010, our previous release.

ASP.NET - Home - New

And of course, our newest release just went live today, December 1, 2011.

2011-12-01 17h00_36

Posted by Jon Galloway | 1 comment(s)
Filed under:

ASP.NET website redesign: Now with less Beta, more Live

Back in October, I posted about the beta release of the ASP.NET website redesign at beta.asp.net. Since then, we've listened to a lot of great feedback, ruthlessly evaluated a huge catalog of content, and continued to reorganize things so you can more easily find useful content. That redesign just graduated from beta to live today.

2011-12-01 17h00_36

This redesign was focused on the following goals:

  • A newer Information Architecture (IA) that scales with different types of content. Trying to get you somewhere useful quickly.
  • Content organized into relevant topic areas (Overview, Videos, Tutorials, etc.) to make information easier to find and to learn a technology.
  • Improved on boarding experience – Developers new to ASP.NET should find it easier to get started and download what they need.
  • Important Samples and Tutorials are positioned prominently in the structure of the site so that they are easier to find.
  • Textual Tutorials are as important as videos - We've heard people want text tutorials more than videos, so we're finding balance between these two kind of content.
  • Improved Social Integration – Community info, pulling from Twitter, Facebook and blogs.
  • A less cluttered user experience to get you where you need to go in fewer clicks.
  • Open Source and Samples - We're looking for new ways to showcase great open source projects and excellent samples.

Scott Hanselman's  and I planned that his blog post would cover the site overview and I'd focus on some specific details, so about the new site  blog covers the overview of what we did, so be sure to read Scott's post for the big picture.

Note: It's going to sound like I'm taking credit for actually doing all this work. I've been very busy, but there were a lot of people involved. There's a dedicated development team working on it, and the closest I got to code or production access at any time was when I updated content in the CMS admin interface (yes, still Umbraco, and I'm very happy with it).

Information Architecture focus

Back in the early 2000's (maybe as early as 2004?) someone pointed me at some online workshop materials from Adaptive Path which explained the process restructuring a website's navigation so that it's focused on the user's needs rather than the business's content. This was a revelation to me, and incredibly helpful as I was a tech lead on a project which moved a 20,000 website (comprised of 20,000 classic ASP pages, each a separate file) to a home-grown CMS running on ASP.NET 1.1.

The point is that what's behind the curtain - the different business units involved, the work that went into producing some aging content a few years ago, the work (administrative and development) involved in changing the navigation structure - none of it matters to me when I'm trying to find information I care about. When I was interviewing for this job two years ago, I had plenty of experience - and frustration - with the ASP.NET site. I actually suggested that if the site couldn't be significantly improved, it was time to get rid of it completely. They still hired me, so I've continued to approach the ASP.NET site in that way - it needs to be useful, or it's not worthwhile.

The steps:

  1. Get the site on a modern CMS (Umbraco, powered by ASP.NET of course) which could allow us to begin efficiently moving and editing content.
  2. Restructure the site navigation around user tasks rather than how our content had been historically grouped.

We took the first step with a site update in May 2010, and began on the second step. We broke out separate content around different technology focus areas (Web Pages, Web Forms, MVC) and started putting content maps on the landing pages for each of those technology areas. Those evolving content maps began to define how the site should be structured.

So, here's a look at how the actually useful content in a page on the ASP.NET site has evolved over the past year, leading up to this new release

Note: Phase 2 below is not the final state, so hang on a second.

  • Start: Seven links at the top, each of which took you to pages with lists of content, usually organized in a way that made them hard to navigate.
  • Phase 1: Surfacing some top links across several categories, but if you click on a "more" link, you go to a huge list of stuff, often hard to navigate. Cluttered with a lot of thumbnails which don't really add any value.
  • Phase 2: Content map added, which is kind of a wall of text, but at least lists out some of the top content by topic.

The content map was kind of a band-aid - it tried to show the structure we wished the site had, but once you clicked through on any of the links the dream collapsed, and there was no real way to navigate around through the pretend structure.

We refined at that pretend structure while it was just content in a page, focusing it on subject matter in a context (e.g. Security in ASP.NET MVC, Performance and Caching in ASP.NET Web Forms). Then, with this new release, we've made that pretend content the real content structure.

The Navigation Tab Structure

The information architecture starts with a common tab format across the three technology focus areas:

Within each of these sections, we've divided content by use:

  • Overview - This provides the main content map, linking to content in other tabs if appropriate (e.g. if you're interested in MVC Security and there happens to be an MVC Security section in the video tab, we'll link you to it. This content map also links to top content on MSDN as appropriate.
  • Tutorials - These are generally multi-part walkthroughs which will teach a subject step by step.
  • Videos - We separated videos out for each technology area, because we consume video differently than we consume textual content. If I'm looking for reference information on a topic and am in skim mode, videos aren't relevant. If I have some time to sit back and watch as someone demonstrates something, I only want to see videos. So, we separated them out, but we linked to them from the overview where appropriate.
  • Samples - This tab lists sample applications with working source code, so you can see things in context. The samples include content from both inside and outside of Microsoft as appropriate, so we include popular open source applications which we think are useful as samples.
  • Forum - The ASP.NET forums have been a great way to discuss issues and get help for a long time, but they've been a bit buried. I'll confess I don't think about them as the resource they are until I stumble across them in search results. We've included a tab which shows the dedicated forum for each technology area.
  • Books - The books section was kind of off on its own before, too. I updated our books list and broke it into chapters which I thought were useful. Since this is now quick to update, I can go in and add new books as the become available.
  • Open Source - We listed some top open source resources in each technology area which will help you in building your applications. This isn't a listing of open source applications running on ASP.NET, it's libraries and tools which will help you as you build your applications. It's of course not complete and can't include every open source resource available, but Scott Hanselman made a best effort at listing open source resources we'd recommend to fellow developers.

Oh, and the structure isn't pretend anymore

The landing page for a technology focus is the Overview tab, and you can see that we've subdivided the content in these areas into Chapters. Here's that same MVC page with that change:

You can really see it as you click into the content, though. That structure follows you around through the site, visible in the breadcrumb and table of contents in the right rail (highlight added to the image to point it out).

Multi-Part Article Navigation

For most of the content, the chapter format worked just fine. For a page showing a video about a Web Pages Security topic, we'd show the Web Page TOC in the right rail with that part of the Security section highlighted. There was one place where we needed a third navigational level, though: multi-part articles.

Most of the multi-part articles are in the tutorials section, since tutorials are often broken into a series of pages. As you work through one of these tutorials, you'll find that your breadcrumb looks something like this: Home/MVC/Tutorials/Chapter 4. Getting Started with EF using MVC/Creating a More Complex Data Model for an ASP.NET MVC Application (4 of 10)

In this case we're in the MVC technology area, in the Tutorials tab, in the Chapter 4. Getting Started with EF using MVC section of the Tutorial table of contents, and we're on the 4th page of that tutorial.

To make the context clear, we mark that kind of content as multi-part, which shows a different kind of navigation in the right rail:

2011-12-01 13h38_16

This shows that you're in a multi-part article, and clearly shows your context.

Content Review

The next step was mapping a lot of content to this new structure and adjusting the structure when we found gaps or additional good content to surface. The site dates back to 2002(!) and has hosted a ton of content during that time. Some of that old content is irrelevant or obsolete, but some of it continues to be useful to developers who are maintaining sites running on previous versions. Additionally, there was useful content which had become orphaned - unreachable via the site navigation - as a result of previous redesigns. We had literally thousands of pages of content, some filled with long lists of content, to evaluate.

My thought process was this:

  1. Is this information useful? If a developer were asking me for information about this subject today, would I recommend this particular page / video / tutorial? If not, delete it.
  2. Where does it fit in our site structure? If it doesn't, does the site structure need to change?
  3. Is this information complete, or would I recommend more information? If there's some available - including on MSDN - should we reference it?

I worked with Scott Hunter, Scott Hanselman, ASP.NET team PM's for each of the focus areas, and the excellent writers and editors on the Web Platform & Tools Content Team (who contribute to and curate content both on MSDN and ASP.NET) to evaluate literally thousands of pages. We did this in two passes:

  1. We split up the lists and evaluated each of the individual pages, recommending cut or keep, and if we were to keep it, where it should go.
  2. After completing that step, we had a series of bug bashes, in which individuals walk through a content area and report everything they thought should be changed. This was iterative - bug bash / fix /repeat.

The site was open during this whole cycle, and we got a lot of good feedback via social networks, the dedicated ASP.NET website UserVoice forum, and from MVP's and ASP.NET Insiders. There's a lot of content here, and it will always be a work in progress, but we think the combined effort has helped to surface a lot more useful content in a way that's easier to find. Please let us know how we're doing - this site's only useful if it's providing you the content you're looking for.

Cleaner Markup, Faster Page Loads

The site was already pretty highly optimized, but we paid attention to the site performance and were happy to see page load times improve across the board.

More Semantic Markup

The previous design had a lot of dated (quaint?) design elements, like rounded corners and gradients, which at the time required a lot of extraneous markup for support across a wide range of browsers. There was a lot of wrapper divs which were there only for styling - kind of ignoring the most important element in HTML: text!

Side note: I find it funny that, now that modern standards natively support rounded corners and gradients, they're not cool anymore.

You can see a big difference in the markup just by looking at beginning of the body tag through the end of the header items. Here's the old design:

<body>
    <form method="post" action="/webmatrix/tutorials/15-caching-to-improve-the-performance-of-your-website?"
    id="form1">
    <div class="aspNetHidden">
        <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUENTM4MQ9kFgJmD2QWAmYPZBYCZg9kFgJmD2QWAgIFEGRkFgICD

Q9kFgJmD2QWAmYPZBYCZg8WAh4HVmlzaWJsZWdkZKrDY1NG1HjNDVKzlZSX2Dy7poMS" /> </div> <div id="content_container" class="content_container"> <div class="header_container"> <div class="header_top"> <div class="header_top_right"> &nbsp;</div> </div> <div class="header_content"> <div class="header_content_right"> <a href="http://www.asp.net" title="Home Page"> <img class="logo" style="border-width: 0px;" alt="" src="http://i2.asp.net/common/header/logo.png?cdn_id=22" title="Microsoft ASP.NET" /> </a> <div id="WLSearchBoxDiv"> <div id="WLSearchBoxPlaceholder"> <input class="search_box" id="WLSearchBoxInput" disabled="disabled" name="WLSearchBoxInput" value="Search" /><input class="search_button" id="WLSearchBoxButton" type="button" value="" name="WLSearchBoxButton" /></div> </div> <div id="mainnav"> <ul class="nav_main"> <li class="first"><a href="/home">Home</a></li><li><a href="/get-started">Get Started</a></li><li> <a href="/downloads">Downloads</a></li><li><a href="/web-pages">Web Pages</a></li><li> <a href="/web-forms">Web Forms</a></li><li><a href="/mvc">MVC</a></li><li><a href="/community"> Community</a></li><li><a href="http://forums.asp.net">Forums</a></li></ul>

 

Yes, that was a bit of VIEWSTATE in there... Also, entire page was full of wrapper divs which were there just for formatting, and if you accidentally messed them up when editing content (oops) the whole page got wacky.

Here's the header markup for that same page with the redesign:

<body class=''>
    <div class='allcontent '>
        <div class="header-wrap">
            <div class="header">
                <a href="/" class="logo" title="The Official Microsoft ASP.NET Site">The Official Microsoft
                    ASP.NET Site</a><ul class="nav-main">
                        <li><a href="/">Home</a></li><li><a href="/get-started">Get Started </a></li>
                        <li><a href="/downloads">Downloads </a></li>
                        <li><a href="/web-pages" class="selected">Web Pages </a></li>
                        <li><a href="/web-forms">Web Forms </a></li>
                        <li><a href="/mvc">MVC </a></li>
                        <li><a href="/community">Community </a></li>
                        <li class="last-child"><a href="http://forums.asp.net">Forums</a></li></ul>

I see that three goals are achieved in unison here:

  1. Cleaner design means less HTML, so the pages load and render faster
  2. Less junk/formatting HTML means the content is easier to maintain
  3. A focus on content over superfluous design elements usually mean that the content is easier to read, as well

Better Performance, YSlow Improvements

Again, the focus on this redesign was really about information architecture and design refresh, but we did pay attention to site performance and best practices throughout because... well, it's the ASP.NET site and we care about this stuff. We want to be proud of this site, and we want you to be proud of it, too.

Scott Hunter, Scott Hanselman, and I were on several calls with the development team every week, and we constantly badgered them about performance tweaks, practices, etc. We started with a B YSlow rating, which is actually pretty good as far as most sites are concerned.

2011-12-01 09h57_16

We ended up with an A, with a discussion about any recommendation we couldn't meet. The only mark against us in the page below is due to some local (non-CDN) images, which was a measured decision to allow content editors to edit them in the CMS. Check the YSlow marks across the site yourself - it's a fun exercise.

2011-12-01 09h58_56

Looking at better performance and best practices ensured we were doing things like setting correct headers, using sprites effectively, minimizing and bundling resources, etc. Again, I did absolutely none of that development work, I just sent e-mails about it. ;-)

We had a team doing weekly performance testing across the site and making recommendations on best practices and opportunities to improve. Here's one of the pretty graphs in one of them showing the page load time was significantly reduced site-wide, often cutting the load time by 50% or more.

2011-12-01 15h17_44

What's Next?

We're definitely not done. We put a lot of things on the post-launch list, many of which are now possible as CMS edits. I mentioned that we've been asking for feedback and using your input to tell us what's most important. Here are some of the things we're tracking:

HTML5 Video

It's highly requested, and it's important to us, too. I prototyped a Silverlight with HTML5 fallback video solution which is in the "works on my machine" state. I went back and forth on which to make primary and which to make fallback, but since it's leveraging standard HTML content fallback (no Javascript or server logic required) it's easy to switch.

As written, this would continue to use the existing player (along with features like time based commenting and cross-browser full screen support), but if Silverlight's not installed or is disabled, the content's shown using native HTML5 video support. If that's not available, we'll show some sort of message that indicates you need Silverlight or a newer browser.

We know this is important so that the content's available across as many devices as possible, and it's high on the list.

Better Mobile and Smaller Device Support

I've blogged recently about how ASP.NET MVC 4 will use CSS media queries and adaptive layout to work well on different sized browsers, and adding adaptive layout is in the works for the ASP.NET site, too.

Fewer / smaller ads

Yes. We hear you, and we're pushing for it. Keep voting for it, it means a lot more when you ask for it than when I do.

Bring back old content

Aha! We've done that! Done. Taking the rest of the week off.

Your Feedback, give it to us

While we do watch for blog comments, by far the most effective way to get us feedback is to vote on our www.asp.net website feedback page on UserVoice. Let us know how we can continue to improve!

Leveraging Background Services and Agents in Windows Phone 7 (Mango)

Earlier this month at DevConnections, I gave a presentation on Background Services and Agents in Windows Phone 7. The next week, I got to join Jesse Liberty on his podcast interviewing Peter Torr, a Prinicpal Product Manager on the Windows Phone team who's written a lot of great content about this exact subject.

Overall, I was very impressed. I've done some basic Windows Phone development in the past, but nothing that really cutting edge. I really liked the way Windows Phone balanced enabling features for developers with protecting the phone's resources.

Side note: why you, Jon?

If you follow my blog, you might wonder what I was doing speaking on Windows Phone, since I don't talk about it much here. If you don't care, skip right on by to the next section...

I'd originally proposed this talk because I thought it looked fun. Later I passed it to Jesse Liberty since he works with Windows Phone all the time, but helped him write up the outline and sample code because I thought it looked like fun (and partly because I'd dumped the talk on him). Then when he found out the week before DevConnections that he'd be unable to attend, I requested to take the talk back, because it looked like fun. This stuff is just plain cool to work with, and I had a blast preparing and presenting on it.

While I don't do a lot of Windows Phone development, I've spent some time pair programming with Jesse on The Full Stack project, which includes a Windows Phone client. One of my main takeaways from that project was that it's really easy to get started with Windows Phone development, especially if you've done some Silverlight development - and I've done a good amount of Silverlight development. There are a few new concepts to wrap your mind around, but I was amazed how easy it was to get up and running.

Background Services - Start with the right mindset

You want your Windows Phone applications to do useful work in the background, but you don't want the background processes to affect the end user's phone experience. By experience, I mean:

  • You don't want them to interrupt or slow down foreground tasks (especially talking on the phone) in any way, ever
  • You don't want them to run down the battery
  • You don't want them to run up expensive bandwidth charges or interfere with foreground network usage
  • You don't want anyone to have to think about them at all

Rather than hope developers will keep the user and the above values in mind and do the right thing, Windows Phone background services provide a great framework for you to work within, and they automatically make sure you're playing within the rules. I think they've struck a great balance here, but when you're developing background services in Windows Phone, you need to keep this always in mind.  Your background services are most definitely managed, and they will play within the rules. It's important to have that straight from the beginning.

Overview of services

Windows Phone background services are easier to understand when you get the idea of how they all fit together. I mentally broke them down into three generic types, with some pre-built "specialist" agents to handle common background use cases.

Note: Some of this logical grouping is stuff I came up with on my own to make sense of all of the different options. It's not officially approved by anyone but me, but it's just a mental model to help you understand what's available. Technically, if you look at the ScheduledAction class hierarchy, Resource Intensive tasks fall right next to Periodic Tasks, but for the sake of understanding what the different types of tasks and actions do, I think it's easier to ignore that for a bit.

2011-11-22 17h10_37

Color coding explanation:

  • Purple are custom tasks
  • Green are pre-built, specialized tasks
  • Blue are general types

Scheduled or Resource Intensive?

Scheduled tasks are things that don't require many resources (e.g. CPU, network) and need to run on some kind of schedule. Resource intensive tasks do require resources, so they can't dictate when they'll run.

The Windows Phone operating system keeps background tasks from abusing resources by making decisions based on how resource intensive they are. Processes that require a lot of resources can only run when conditions are met (e.g. while charging or when battery power is high), and processes that run periodically or on a schedule can't use a lot of resources.

Whatever, you say. I'll do what I want when I want because I'm a rebel. But, no, it's not that kind of setup here in background task land. For stealing tools, cooler. If your task doesn't abide by the rules, it's terminated.

Resource Intensive Tasks

Resource Intensive agents run for a relatively long period of time when the phone meets a set of requirements relating to processor activity, power source, and network connection. An example here would be performing a long-running computation, or uploading a lot of data to a service.

Since by their nature these tasks are expected to use resources, they're only allowed to run when resources are plentiful, e.g.

  • External power required
  • Non-cellular connection required
  • Minimum battery power: 90%
  • Device screen locked
  • No active phone call
  • Can't run longer than 10 minutes

Built-in Resource Intensive Tasks

There are two built-in resource intensive task specialists - Background Audio and Background File Transfer. Since their use-cases are more defined, some of the above requirements are relaxed.

Note: I've decided to lump background audio and background file transfer under Resource Intensive tasks because they make some logical sense there - they do suck up resources, and they aren't scheduled. That's my logical grouping, it's not anything official.

Background Audio

Background Audio lets you queue and play audio while your device isn't active or even running. I showed two examples during my talk - one which queued up a bunch of tracks which continue to play when you navigate away, and another example which plays a ticking clock in a Pomodoro application to remind you that you're still "on the clock."

The architecture of Background Audio is fascinating. It takes a little bit to figure out who's doing what, but it's really well put together. First, meet the two main players:

Audio Player Agent

It's your job to create the Audio Player Agent. You can do that by adding a new project to your solution and selecting one of the two Windows Phone Audio Agent project types (Playback or Streaming).

2011-11-22 21h45_25

Of course, you can write the code by hand if you prefer, but there's little point. This project template adds the necessary references and drops a single class into your Audio Player Agent project - a class which extends the AudioPlayerAgent base class and handles two events:

OnPlayStateChanged - this is where you put the logic for when a track ends or is ready to be played

OnUserAction - this is where you respond to user input - things like play / pause / skip next / skip previous commands

The important thing to get here is that your Audio Player Agent class is completely responsive. Its only purpose is to respond to events.

Background Audio Player

There's only one Background Audio Player, and you don't own it. It belongs to the operating system, and you talk to it through its static BackgroundAudioPlayer.Instance property. Your application issues commands (requests?) to the Background Audio Player instance, which raises events in your Audio Player Agent.

So your application code talks to the Background Audio Player Instance, which talks to your Audio Player Agent - your application code never talks to the Audio Player Agent. This makes sense when you remember that your application may be tombstoned or closed immediately after talking to the Background Audio Player, which doesn't matter - the Background Audio Player calls into your agent without having to spin up your application. Here's the diagram from MSDN that shows this communication:

Note that the diagram shows the Background Audio Player is using two other operating system level components to play the music - the Zune Media Queue and the Universal Volume Control. This ends up giving a great experience to the end user with little work on your part: you queue up the audio, and the user can control the volume through a standard interface.

See the Background Audio Overview on MSDN for more information on how these parts work together.

Background Audio Tips

Here are a few good things to keep in mind when developing background audio applications.

  • For development, you can use F9 (volume down), F10 (volume up), and F11 (play/pause).
  • Your background audio can be either an internet URL or a file in Isolated Storage. If you have audio you need to move to Isolated Storage, see Jesse's post on how to do that.

Extra Credit: Background Audio Agent registration

Just because I'm one of those people who can't take "just because" for answer, I needed to know how the Background Audio Player knew how to find my application's Audio Player Agent. It turns out that's set up in your main application's WMAppManifest.xml (in the Properties folder). If you take a look at that, you'll see a section in there that lists tasks:

<Tasks>
  <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
  <ExtendedTask Name="BackgroundTask">
    <BackgroundServiceAgent Specifier="AudioPlayerAgent" 
                            Name="AudioPlaybackAgent1" 
                            Source="AudioPlaybackAgent1" 
                            Type="AudioPlaybackAgent1.AudioPlayer" />
  </ExtendedTask>
</Tasks>

Background File Transfer

The Background File Transfer service lets you register files for upload or download, and it takes it from there. It waits until appropriate conditions are met - for example, it only transfers small files over cellular networks, waiting for wi-fi or wired connection to transfer larger files - and raises events which your application can handle if it's running. It's all very fire-and-forget.

A few things to be aware of here:

  • The service won't run until conditions are met. The operating system imposes some, and you can add additional restrictions. The important thing to realize here is that the conditions may never be met, so the file transfer will never happen. If you've requested a large file download which exceeds the cellular limits, but you have a user who never uses a wi-fi connection, they'll never get the file. So the responsibility is on your application to handle those exceptions.
  • Mango has great support for HTTP, so you can make use of headers like If-Modified-Since and ETAGs to optimize transfers.
  • You get both progress and completion events, so your UI can display status to users if they'd be interested.
  • You don't need a separate agent here. You register a TransferRequest with the service and subscribe to the events, but you don't need a service because the transfer service doesn't need you to respond to anything if your application's shut down.

Custom Resource Intensive Tasks

If you need to do something resource intensive - other than audio or file transfers - you can create your own Scheduled Task Agent. You do that the same way we added the Audio Player Agent previously - there's a project type just for that. These agents just have one method: OnInvoke. That's where you do all your resource intensive what-have-you. As I mentioned earlier, there are a lot of constraints on Resource Intensive Tasks, summarized in MSDN.

My main takeaway is that you can do some neat things with these, but you need to account for two things:

  • You don't know when - or if at all - your user's phone will run your task.
  • If your task misbehaves, it will be terminated. Just like that.

Here's how you'd register you Resource Intensive Task:

resourceIntensiveTask = new ResourceIntensiveTask(resourceIntensiveTaskName);
resourceIntensiveTask.Description = "This demonstrates a resource-intensive task.";
ScheduledActionService.Add(resourceIntensiveTask);

Scheduled Tasks

As with Resource Intensive tasks, you have a few options with scheduling. If you just want to notify the user, you can take advantage of some built in notifications (alarms and reminders); if you need to do something else you can create a custom Periodic Task.

Notifications

You've got two types here: Alarms and Reminders. Both are scheduled for some time in the future with a few lines of code, and that's it as far as your app is concerned. There are a few minor differences between the two:

  • Alarms will always have a title that says "Alarm" while Reminders can have a custom title
  • Alarms can play a custom sound, while Reminders will always play the system reminder tone
  • Tapping on an Alarm will launch the app and take you to the initial page of the application, as if it were just being launched. Reminders can include a navigation URI to a page inside your phone application, and it can contain querystring information as well.

Registering an alarm or reminder is pretty much identical, with the only difference being in supported properties. Example:

Reminder r = new Reminder("Break_Over");
r.Title = "Back To Work";
r.Content = "Break's Over!";
r.BeginTime = DateTime.Now.AddSeconds(10);
r.NavigationUri = NavigationService.CurrentSource;
ScheduledActionService.Add(r);

Periodic Tasks

Periodic Tasks aren't really scheduled in the way I first assumed. They can be set to run as often as 30 minutes, but that time may drift by as much as 10 minutes. They may not run every cycle, depending on how busy the operating system is. They'll be terminated if they run longer than 25 seconds, but may be terminated sooner if the operating system decides it needs to.

The point is that the Periodic Task system isn't a scheduler. It's a way to do light, low resource work in the background - small internet communications, updating a tile, etc. They're great for keeping the users phone up to date with nice to have information, but you have to assume that the task may run less often than you'd hoped, or potentially not at all.

Creating a periodic task is really easy - it's the same idea as creating a resource intensive task. You add a Scheduled Task Agent to your project, then register it with the Scheduled Action Service like this:

periodicTask = new PeriodicTask(periodicTaskName);
periodicTask.Description = "This demonstrates a periodic task.";
ScheduledActionService.Add(periodicTask);

A couple of tricks

Removing tasks before adding them

There are a few tricks to be aware of. First, the Periodic and Resource Intensive Tasks are registered by name - a string. So the above code I showed for both of them is overly simplistic - it will fail if you try to schedule the same task twice. The proper pattern is to find and remove the task before adding it:

periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;
if (periodicTask != null)
{
  ScheduledActionService.Remove(periodicTaskName);
}

periodicTask = new PeriodicTask(periodicTaskName);
periodicTask.Description = "This demonstrates a periodic task.";
ScheduledActionService.Add(periodicTask);

Launch for testing

Many of these things would be tough to test in normal conditions. For example, a there's no way I want to wait around 30-40 minutes to see if my Periodic Task will run correctly. Fortunately, you can use LaunchForTest to schedule a task when you're in debug mode.

#if DEBUG_AGENT
  ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(60));
#endif

Toast

If you're running background processes, you may need to alert your users when things happen - completed task, failed task, significant task progress, etc. You can do that using ShellToast.

ShellToast toast = new ShellToast();
toast.Title = "Have some toast";
toast.Content = toastMessage;
toast.Show();

Slides, Podcast, Code

Here are the slides for my presentation at DevConnections:

Here's the podcast with Jesse Liberty, Peter Torr, and me talking about background services and agents in Windows Phone:

Yet Another Podcast #52 - Peter Torr on Windows Phone Multitasking

Code samples from my demos are available here.

Jesse and Peter have both written about Windows Phone multitasking topics on their blogs:

Posted by Jon Galloway | with no comments
Filed under:

15 Pragmatic JavaScript Tips for ASP.NET Developers

Here are 15 pragmatic JavaScript tips for ASP.NET developers from my recent presentation at DevConnections 2011 (Las Vegas).

The goal here is pragmatic tips - things you can use right away. Three or four are specific to ASP.NET Web Forms, the rest are pretty cross-cutting and in some cases apply to any web development platform. These are pragmatic tips, not advanced JavaScript development or coding practices, although I did sneak in a bit of SignalR, Node.js, and CoffeeScript at the end. If you're looking for coding practices, I'd highly recommend Elijah Manor's MIX11 talk: Good JavaScript Habits for C# Developers.

Damian Edwards has given a similar talk several times over the past year and kindly shared his samples and advice - his talks are all available here. His talks covered a lot of great information, and my updated talk also included some future / edge stuff, like RIA/JS, Visual Studio 11, ASP.NET 4.5, Node.js, and CoffeeScript. Since I was covering a ton of information in an hour, I opted to structure this talk as a series of 15ish tips, building from the simple and easy material to, well, stuff like SignalR and Node.js with WebMatrix and iisnode.

Slides are here:

I set up a new repo for presentations (slides and code) on Github; here's the sample code for my demos. My presentation wasn't filmed, but Damian's talks at MIX and TechEd were. Links to those videos are in the presentation section of his blog.

Okay, enough talking, more tips. Here we go:

Tip 1: If you’re using Ajax Control Toolkit, get the newest releases

It's been a while since I used the Ajax Control Toolkit, but it's still apparently very popular (substantiated by a show of hands at the presentation). The tip here is that - if you're still using Ajax Control Toolkit - you should be aware that there are regular new releases, and that they're available via NuGet.

Recent releases include several new controls, including Gravatar, Twitter, and a new HTML editor. The new releases also include top fixes from the issues list, and there's a real emphasis on quality - as shown by the automated browser testing with QUnit. You can read more about recent updates on Ajax Control Toolkit from Stephen Walther.

The overall guidance from the ASP.NET team is that they're recommending jQuery for client-side coding. That's where future focus, project templates, code samples, etc., will be. However, if you're using Ajax Control Toolkit, you should be on the latest releases. It's easy to do now, since Ajax Control Toolkit can be installed and updated via NuGet.

Tip 2: Get to know jQuery

Sure, no surprise there. All web developers should know about jQuery, and if you're not using it you should have a pretty good reason. Here are the top advantages I listed:

  1. DOM abstraction
  2. Selector engine (I explained selectors using this Interactive jQuery Selector Tester page)
  3. Plugin ecosystem
  4. Leverage CDN’s (talked about how end users have to wait for your custom scripts to download, while jQuery is very likely cached by their browser)
  5. Included in Microsoft templates (showed that File / New Project will put jQuery in your application)

I pointed out that JavaScript is beautiful and elegant, but sometimes extremely tricky. We looked at variable hoisting as an example. The point is that JavaScript can be a bit tricky, and writing your own libraries when jQuery does it better is an unnecessary code liability to take on.

Tip 3: Install and Update jQuery via NuGet

ASP.NET MVC 3 already includes jQuery as a NuGet package, so it's easy to upgrade when a new version comes out. I showed how to remove the jQuery scripts from an ASP.NET Web Forms application and add jQuery via NuGet to get that same upgrade experience. We looked at adding jQuery plugins via NuGet, too.

Tip 4: Know how to find and use jQuery plugins

I explained what plugins are used for, and showed three great ways to find and use jQuery plugins:

I showed the jQuery theme support, and we hooked up a few jQuery UI datepickers to ASP.NET textboxes.

Tip 5: Use jQuery UI via Unobtrusive Wire-up

Damian's written a nice jQuery plugin to wire up jQuery UI widgets via HTML5 data- attributes, and it works for standard HTML and ASP.NET Web Forms controls. Here's an example:

<asp:TextBox runat='server' ID='startDate'
    data-ui-fn='datepicker' />
<div class='status-box' data-ui-fn='draggable resizable'>
    I'm a Drag and Droppable, resizable content area.
</div>
Joe Stagner has a full walkthrough on this here: Unobtrusive JavaScript in your ASP.NET pages

Tip 6: Write your own jQuery plugins

We walked through turning some of our jQuery code into a plugin, making use of the jQuery Code Snippets for Visual Studio 2010.

Plugins offer some great benefits, even if you never plan to distribute your plugin:

  • Code encapsulation
  • Reuse throughout one site or a number of projects (I talked about an example where my team bundled common jQuery code into plugins, and we were later able to leverage them from content input via CMS users)
  • Standard, tested modularization system that's designed to work well with jQuery

A good way to get started with writing your own jQuery plugins is the Plugin Authoring Tutorial on the jQuery site. It's really well written, starting with simple cases and slowly introducing advanced topics and best practices.

Tip 7: Take advantage of Visual Studio’s JavaScript support

I showed off some of the JavaScript editing and Intellisense features that are included in Visual Studio 2010. A lot of people aren't aware that the Intellisense infers type and can handle dynamic variables, loops, etc. Neat stuff.

See Scott Guthrie's post, JavaScript Intellisense Improvements with VS 2010, for a nice walkthrough.

Tip 8: Get ready for Visual Studio 11 JavaScript features

Okay, Visual Studio 2010 has some nice JavaScipt editing features, but Visual Studio 11 Developer Preview is a huge advance here. It's actually using the same engine that's used in the Internet Explorer Developer Tools, and Visual Studio 11 adds a lot of goodness like implicit references (configurable by editing a JavaScript file), brace matching, outlining, etc.

More on those features here: http://bit.ly/vs11javascript

Since Visual Studio 11 Developer Preview works side-by-side with Visual Studio 2010, you can start using those features today. Yes, it's pre-release, but I'll give it the Works On My Machine certification - I've been using Visual Studio 11 Developer Preview side-by-side with Visual Studio 2010 since //build and it's been working great. Visual Studio 11 Developer Preview starts up so quickly, I'm often using it in cases where I would have used Notepad++.

Tip 9: Use the Visual Studio 2010 JScript Editor Extensions

Ah, you say, Visual Studio 11 Developer Preview is neat, but that's not what I call pragmatic. It's not out yet!

Fine, there are some great Visual Studio extensions which give you a lot of the great features in Visual Studio 11 in Visual Studio 2010. That's no accident, some (like the Web Essentials extension) are written by the PM's who are driving the Visual Studio 11 features.

The Visual Studio JScript Editor Extension adds a lot of the Visual Studio 11 JavaScript editing goodies to Visual Studio 2010. Things like:

  • Brace Matching
  • Outlining / Code Folding
  • Current Word Highlighting

Is this pragmatic? Sure! It's a free, quick install, and if you do any JavaScript editing in Visual Studio it will pay for itself in no time!

Tip 10: Use ASP.NET 4 ScriptManager features

Okay, if you're using ASP.NET 4.0 Web Forms, you need to know about the new features in ScriptManager. In my talk I demo'd how easy it is to use CDN's and how to register scripts like a Ninja Pirate Honey Badger with ScriptManager.ScriptResourceMapping. Script Resource Mappings offer a number of benefits:

  • You can register a library like jQuery by a version independent name ("jQuery"), so upgrading jQuery versions means that you only need to update the mapping in one place, rather than throughout your code
  • Using Script Resource Mappings really helps in cases where you may be referencing a library multiple times (e.g. in a page and in a multi-instance user controls within that page) since it will only include the script once

Pragmatic? Yes! This shipped with ASP.NET 4.0 (April 2010), and taking advantage of resource mappings and automatic CDN usage means you'll have more maintainable, higher performing, better script references with minimal effort.

Tip 12: Use RIA/JS for WCF services

RIA/JS is a set of jQuery plugins for accessing RIA Services DomainService and OData services. My demo - for this (which was unfortunately pretty rushed) covered the BigShelf sample from the RIA/JS team, which shows how you can use WCF RIA Services to access WCF services from a browser using a really efficient JavaScript library. It includes full featured services, and your service calls are all using really light-weight JSON.

The best way to get up to speed on what's new - and coming - in WCF RIA Services is to watch Dinesh's talk at BUILD. Jeff Handley posted a good summary of the updates for //build which explains what's been released and what's in the works. The short summary is that if you're calling into WCF services from the browser, you should strongly consider using RIA/JS (Mea culpa).

Tip 13: Use SignalR for long-polling

Yeah, this is tons of fun. SignalR is a "smart" way to do long-polling with ASP.NET. For an example, I ran the StackExchange chat application and showed that each request was polling - sending a bunch of repetitive requests to the server, asking "Anything new? How about now? Now? Anything? Hey, anything new?"

HTTP Short Polling

SignalR is a nice system (both client and server libraries available) which implements long polling, in which the browser makes a request and the server waits to respond (keeping the connection) open until there is new information to send to the client.

HTTP Long Polling with SignalR

You could implement this pattern on your own if you worked at it, but there's a good chance you'd be tying up threads on the server for each open request. Some smart guys on the ASP.NET team have set up this library to leverage stuff like the task parallel library, websocket support (if the browser supports it), takes advantage of async / await, etc.

Is this pragmatic JavaScript? Absolutely! This is real, working code, you can install SignalR immediately via NuGet, and it improves scenarios in which the client is waiting for updates from the server because it's more performant and will return information to your clients immediately, rather than waiting for the next time they poll. The source includes some great samples, including some multi-user applications like chat and a collaborative shape / drawing example.

You can find out more in Scott Hanselman's recent post, Asynchronous scalable web applications with real-time persistent long-running connections with SignalR.

Tip 14: Server-side JavaScript with iisnode and Node.js

Node.js is a popular system for writing server-side code in JavaScript, and it's optimized for high performance and asynchrony. I wrote a big post on it recently: Using Node.js in an ASP.NET MVC application with iisnode.

Is this pragmatic? Well, this one is stretching things a bit, but I couldn't help myself. You can use Node.js in IIS using iisnode (even integrating it into an ASP.NET site, since iisnode runs as a standard IIS handler), and it works today. The Node.js community is big, and there are a ton of great packages available now. Is it likely people will start integrating Node.js into their ASP.NET Web Forms applications any time soon? Hard to say. One advantage is that you can reuse JavaScript code on client and server, which could be a big advantage if done right.

Tip 15: Adventurous? Keep an eye on CoffeeScript

Early on, I talked about the fact that JavaScript is powerful, but can be a bit tricky. Some of this is due to the fact that JavaScript is a dynamic, prototype based, weakly typed language masquerading under Java syntax. CoffeeScript is a "little language" that compiles into JavaScript:

Underneath all those awkward braces and semicolons, JavaScript has always had a gorgeous object model at its heart. CoffeeScript is an attempt to expose the good parts of JavaScript in a simple way.

One benefit of CoffeeScript is that it automatically prevents you from accidentally shooting yourself in the foot due to strange language quirks. If you're writing a lot of JavaScript, CoffeeScript is definitely worth a look. I recently wrote An introduction to CoffeeScript which explains how it works and how to get started.

What about you?

Okay, that's my list. Got any tips you'd like to share?

More Posts Next page »