Morten Bock

.Net developer


The hasbang controversy

The other day I responded to a tweet about using prerendering tools to serve JS driven pages to crawlers.

Afterwards a twitter debate followed, and as usual, much is lost in a debate limited to 140 char chunks. Basically the opinion was that if you use hashbang urls, you are the spawn of the devil, and you will kill all the kittens in the world Wink.

I will try to present my argument why I think using hasbang urls can be an acceptable solution to a specific problem. 


For the purpose of an example, consider a company, Acme Cloth Inc, which is an imaginary online retailer of clothing. This company has a Shirts category on their website, which they want users to be able to filter in a nice manner. That means that the following features should work:

  1. When a filter has been applied, then the user should be able to bookmark it and share it
  2. The list should update without a page refresh, when a filter is set, to improve usability and performance
  3. The filtered url should be crawlable by search engines

The browser demographics statistics of the site show that 10% of the users us IE 8/9, and those users generate 20% of the revenue (these stats are from a real site at the time of writing)


In a modern browser, achieving the above objectives is not a problem. Using the pushstate browser API, it is entirely possible to update the url without causing a page refresh. For example, the url for a filtered page could look like /shirts/nike/green.

This is a very nice solution, which also makes the urls crawlable by default. The problem is that IE 8/9 do not support pushstate. Since those browsers are a big part of the revenue, we want to treat them at first class citizens in our website.

If we continue with the pushstate solution, then we will have to give up either the url history or the ajax loading of the products when filtered, but that also means that 10% of our users will get an inferior experience.

Enter the hasbang #!

The hashbang is a convention that Google supports, where you can specify that urls containing #! are actually JS driven pages, and then ask Google (and other bots) to fetch the page in a server rendered form, be requesting the hash as a query string. So a url like /shirts#!/nike/green would be requests by Googlebot like /shirts?_escaped_fragment_=%2Fnike%2Fgreen which would then tell you server to fetch the data directly instead of serving the Js driven page.

Why is this helpful? Well this invites IE 8/9 users to the party, since using hasbang url's like /shirts#!/nike/green enables those browser to keep a history of the filter changes in the url, and bookmark those.

The downside is that when users load a page with a hasbang url, there will be a slight delay before the content is loaded, since in must be fetched by a separate ajax request. However this can be optimised, and you can work with perceived performance to improve the experience of that first page view. Subsequent filtering will be very snappy, because there will be no page refreshes.

Problem solved?

The hashbang solution lives up to the 3 criteria we set out with at the beginning. Also for the IE 8/9 users. In the case of Acme Cloth Inc, this means that we can provide a good service to a loyal customer group, which will most likely improve the revenue stream. 

You can argue that this is not the "right" way to build websites, based on the way the web *should* work. It is a fair point, but I don't think you should build a website just to satisfy you principles, you should build it to serve your users. 

Is the hashbang a hack? Sure. Is it worth it to support user that supply 20% of your revenue? I think so! Should you use it on your website? That depends very much on your browser demographics. The pushstate solution is much cleaner, and is the future of the web, and you can decide if you think you can supply a service that is good enough for the IE 8/9 users, without either the history or the ajax features.

What about clients without JS? If you have significant number of this type of users, then you probably don't wan to use hashbang urls. As always, use the solution that fits your problem.

There, that is my opinion on the matter, in more than 140 chars Smile

Shared Google calendars on the Nokia Lumia 1020

I just got my new Lumia 1020 which runs Windows Phone 8, and wanted to set up my Google stuff to sync with the phone. I use two factor auth, and after creating an application specific password, it synced up alle my email, and my own calendars.

But my wife's shared calendar did not show up, and given the history of issues between google and Windows Phone, I started searching for a solution. The Lumia 1020 is no longer using Active Sync, so all the old guides were no longer relevant. By pure luck, I stumbled on a post with this link:

That will let you select which calendars should be synced when using CalDAV access, which is what the Lumia 1020 is now using.

You might need to remove/save/add the checkbox for syncing calendars for your google account on your phone before it shows up, but I now have the shared calendar in there as well.

I hope this might help out others struggling with this.

Profiling MVC views in Umbraco 6

As you might know, Umbraco 6 includes the MiniProfiler out of the box. This is great, as it gives everyone a chance to figure out what parts of your site might not be performing as well as they could. However, I discovered that sometimes the results that you get can be somewhat misleading, and I decided to dig into it a bit further.

My solution looks like this:

When I ran the profiler on my page, it looked like this:

So, for some reason, it is taking almost 85 milliseconds just to find a view? So I started looking into why it might take time to look for views, and made sure that my application was in debug="false" mode in order for the view engines caching to be enabled.

That didn't help. I was still spending 85 ms for each request. But hey, who needs "TopNav" anyway, right? So I removed the surface controller from my Home view. Now it was just the "DisplayTemplates/Product" view taking time to be found. This is starting to smell.

After looking into the Umbraco source, I could see that it was adding it's own viewengines to the mix, and they had some file IO code in there, so I thought, maybe that's the problem. Then I created my own profiling view engine wrapper, and added it to my project.

Since Umbraco already wraps it's view engines in the default profiler, I had to change it up a bit:

using System.Web.Mvc;
using Umbraco.Core;
using Umbraco.Web.Mvc;
namespace UmbMvcMiniProfiler
    public class Bootstrapper : ApplicationEventHandler
        protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            ViewEngines.Engines.Add(new MyProfilingEngine(new RenderViewEngine()));
            ViewEngines.Engines.Add(new MyProfilingEngine(new PluginViewEngine()));

Great. Let's see which one is the sinner!

WTF? So now it seems that almost no time is spent in the actual view engines? But there are some big jumps in the "from start" column, for each of the products. I'll update my profiler to also wrap the views, and put a profiler step in the .Render call.

Allright, now we're getting somewhere. What could be taking time in my Home view? Well, I'm iterating a list of products, maybe I should make sure that list is a Product[]?

And boom. Turns out that the view engines and the views aren't really that slow. The problem was in my Index action where I was mapping my products. It had (conveniently for this example) a Thread.Sleep() for each product.

So there you go. A way to profile what i actually going on in you views and view engines. Full Gist with the profiling code is here.

I still do not know what the heck is going on with the default profiler, and what it is actually trying to do, but it sure confused me more than it needed to. Looking at the source of it, I still don't know what it's supposed to do?? But I thought this might be handy for others wondering why it takes so long to find their views.

Slides from my UmbDkFest presentation

I had the pleasure of presenting a case about at the Umbraco DK Festival last week. The talk focused on how we implemented a large site with many languages and editors in Umbraco.

If you would like to take a look at the slides, I've uploaded the PDF here.

Thanks to the Kraftvaerk guys for making a good event, and thanks to those of you who stopped by. Let me know if you have any questions.

The industry of heroes and dreamers

When I was younger, all I wanted was to be a musician. It was a magical thing where everyone seemed to have a common ground, and were creating something from their heart, which would mean something for a lot of people. Anyone can pick up an instrument, and start practicing, and start creating. Some are great, some are not. But anyone can do it.

Everyone who plays has at some point started by plucking at a guitar string, or playing on the piano in the living room. That is the connection between the beginner and the superstar. The very first notes. The only thing between them is effectively the number of notes played.

So you start by playing a note. Then trying to combine them, and as time goes by, you will get inspired by notes that others have combined and shared with the world. Some were played many years ago, and others have just flowed through the ether for the first time. But they are all there to be heard, and inspire those willing to hear them.

Music is a magical industry where some are raised to fame, for one reason or another. Not only among listeners, but also among fellow musicians all over the world. It is an ever evolving art between creators sitting in the wee hours of the morning, trying to bend the notes just right.

I did never become a musician. And at times I think of what it would have felt like to be one. But I've come to realize that being a developer actually has many similarities to what I think a musician experiences.

We are fortunate to be in an industry that is proud to share experience and knowledge between all levels of developers. We all have the opportunity to learn from our peers, be they colleagues, rising stars, heroes or dinosaurs.

It would not be far fetched to find the developer equivalents to The Beatles, Jimi Hendrix, Eminem or whatever floats your boat. Some have set the bar, and some are pushing the limits. And because of the culture that exists in software development, we all get to know about it. Be inspired by it.

I don't know if other industries have the same luck that we do. Will accountants read interviews with the godfathers of accounting? Are there ground breaking wizkids pushing the boundaries of public transport?

I do know, that I enjoy listening for inspiration no matter if it comes from Miles Davis, Bon Iver or Hanselminutes, and I am proud of our industry for creating that possibility.


Thanks to Scott Hanselman, for sparking this thought with his conversation with Paul Lutus.