Sunday, February 28, 2016

Sitecore Decennial Series #1 - Know your item, remember your context

Understand the basics

The most common problems I find when working with (other people's) Sitecore solutions, has a root cause in either a lack of understanding of the basic concepts of Sitecore and/or a misunderstanding of same. I don't actually know if this is surprising or to be expected - it is what it is.

I'll try and isolate some of the most common basic mistakes, in no significant order. This is also to say, I consider them ALL equally significant ;-)

1. Understand your Item

Yes I'm talking about you, Sitecore.Data.Item.

Chances are, Item is one of the very first concepts you come across when you start developing your first solution. It might look something like this:

    Item home = Sitecore.Context.Database.GetItem("/sitecore/content/home");
    string headline = home["Headline"];

Simple, yea?  Not so. Reading the syntax like this has a high risk of tricking your mind into thinking a lot of things, all of which are false and will lead you astray sooner or later.

1a. A context is implied

As with the very large majority of all interaction with the Sitecore API, a context is required for any interaction. I will dig into this in detail a bit further on.

That method call, is just a method overload for a call that looks like this:

    Item home = Sitecore.Context.Database.GetItem("/sitecore/content/home", 
                Language.Current, 
                Version.Latest);

Why is this significant?  It's significant because here, as in most API calls, Sitecore breaks out and pulls additional information required to execute the call; in this case it needs to determine what Language Version of the Item to get. And once it knows the language, it needs to know which Version of the Language Version to get.

And while this may not seem obvious to you while still learning the robes of Sitecore development (it didn't, to me), this is actually very significant.

Very many things in the Sitecore API requires some sort of context. And knowing them will be important to you, when you advance into more advanced development.

1b. People say "Item" when they really mean "Item Version".

There really is no such thing as an "Item". Item is a construct in Sitecore that holds a lot of information related to the content of the Item Versions - but really holds none of the actual content. (For the advanced readers; I realise we could argue the merits of this - but as a general principle, this holds true).

So what is on Item?    Important things. Like:
  • Name (by default, defines the URL string for the item)
  • Security
  • Template (could also be called the "Schema" for the Item Versions)
  • Statistics (Last Updated, Updated By, etc.)
  • Publishing Information
  • Workflow Information
  • Validation Rules
But for most intents and purposes, not things you need in your day to day life of creating Accordion components or whatever your task.

Sitecore.Data.ID uniquely identifies any Item in a Sitecore solution. And from this, we now also see, that Sitecore.Data.ID does not adequately represent an Item Version.

1c. Understand the different identifiers. ID is not always what you need.

Unbeknownst to many, judging from rarely I find these in use in Sitecore solutions I look at, Sitecore actually has many better options than Sitecore.Data.ID available. All in the Sitecore.Data namespace.

Given this piece of hackety webforms code (had to destroy the BR tags to keep Blogger happy):

  var home = Sitecore.Context.Database.GetItem("/sitecore/content/home");
  litOutput.Text += $"ID (home.ID): {home.ID}$br />";
  litOutput.Text += $"Uri (home.Uri): {home.Uri}$br />";
  litOutput.Text += $"DataUri: {new DataUri(home.ID, home.Language, home.Version)}$br />";
  litOutput.Text += $"ItemUri: {new ItemUri(home.ID, home.Language, home.Version, home.Database)}$br />";
  litOutput.Text += $"VersionUri: {new VersionUri(home.Language, home.Version)}$br />";

The output is:

  ID (home.ID): {DAC24EDD-44FB-42EF-9ECD-1E8DAF706386}
  Uri (home.Uri): sitecore://master/{DAC24EDD-44FB-42EF-9ECD-1E8DAF706386}?lang=en&ver=1
  DataUri: sitecore://{DAC24EDD-44FB-42EF-9ECD-1E8DAF706386}?lang=en&ver=1
  ItemUri: sitecore://master/{DAC24EDD-44FB-42EF-9ECD-1E8DAF706386}?lang=en&ver=1
  VersionUri: en, 1

Any Item you have instantiated (like from a GetItem() API call) will be uniquely identified by an ItemUri, as found on the .Uri property. .ID tells you only the ID of the underlying Item.

From this we also learn, that the Item we get from the API does not exist outside of a Sitecore Context. With both Database, Language and Version information. This is undoubtedly become a pet peevee for you at one point or another, if you start looking to do Unit Testing or any kind of abstractions to the Sitecore API. My honest advice; leave this be for now. For at least a couple of years into your Sitecore learning curve.

Keep your Item identifiers in mind. Don't use .ID as a cache key when publishing Item Versions. Do use DataUri, ItemUri and VersionUri as appropriate, don't re-invent the wheel with your own bespoke implementations or - worse - just ignore the fact that ID does not tell you all you need to know.

Speaking of pet peevees, here's one of mine.

2. Understand your context

2a. Don't break context or get a context you don't require

Given the following code:

    public Item[] GetNewsInCategory(Item categoryItem)
    {
        List articles = new List();

        if (!string.IsNullOrEmpty(categoryItem["Articles"]))
        {
            foreach (var articleId in categoryItem["Articles"].Split("|".ToCharArray()))
            {
                articles.Add(Sitecore.Context.Database.GetItem(articleId));
            }
        }

        return articles.ToArray();
    }

Actually there are 2 pet peevees of mine in here. One is not using the Sitecore API to properly deal with the MultilistField. The other is the breakout to Sitecore.Context.Database to get the items defined in the field. Why? We already take an Item as a parameter, so we already HAVE a Language and a Database context. At the very LEAST, do this:

    articles.Add(categoryItem.Database.GetItem(articleId));

In the inner loop. If you make methods and these happen to take an Item as an argument, by all means USE the context of that argument to carry on. You'll be happy you did, as you will one day find yourself wanting to call your code from say an Index Handler, an Item Saving event or whatnot - and you cannot assume you have your normal page context available in these cases. I've seen what happens on this particular road to hell, and it usually ends up with a line of code like this getting injected.

    database myDb = Factory.GetDatabase("master");

To try and solve the problem, with Sitecore.Context.Database being NULL in some cases. No, no, no, nope, please, just don't. Use the .Database property of the Item you're dealing with. Whoever instantiated it, already made a context for it (see above; no Item with no context).

That said; what the above code SHOULD look like this this. (Leaving out the argument about argument assertion for now).

    public Item[] GetNewsInCategory(Item categoryItem)
    {
        MultilistField articlesField = categoryItem.Fields["Articles"];
        if (articlesField != null)
            return articlesField.GetItems();
        return new Item[] {};
    }

2b. Context, context, context everywhere

I think you realise by now, I find the subject of Context in Sitecore very important ;-)

Here's the thing. Try and avoid using it. While it is indeed very convenient to just jump out and grab a Sitecore.Context.Site whenever you need it, or Sitecore.Context.Language or whatever it may be. But it is also very bad form for your code. It is in fact an anti-pattern.

"But all of Sitecore is written like this?"

CAREFUL!  PERSONAL OPINION WITH SOME SPECULATION FOLLOWS!

Yes. I don't know what to tell you. I'm pretty sure if the original development team was to start today, much of this codebase would have been done following a different mindset. But most of the codebase you're looking at is between 10 and 15 years old, and Sitecore has always been adamant that backwards compatibility be preserved unless there were very good reasons to break it. They follow principles followed by Microsoft very closely when it comes to this.

A good example of this is my own CorePoint.DomainObjects, one of the very first public ORM mappers for Sitecore. Written almost 8 years ago, and it can still be built on recent Sitecore versions without too much headache.

Sitecore uses static constructs all over the place. It will drive you nuts if you try and code to modern standards, e.g. using Dependency Injection (you should), but that's just how it is. I tell you another thing though; calling through a layered API of static methods and classes is faster than dynamically resolving types at runtime. While we accept this cost today, performance was a much different beast 10 to 15 years ago.

So anyway. Back to my original point. Forgive me for pointing out the obvious here. YOU'RE NOT WRITING A CMS SYSTEM. What you're doing, is writing a codebase that will eventually turn out to be an excellent Sitecore solution, running the website of your (or your client's/employer's) dreams. Nowhere is it stated, your code standards need to follow those of Sitecore. Yes, you need to adhere to Sitecore Best Practices in your interactions with the Sitecore API and all that, obviously, but nothing else in Sitecore dictates how you should organise your project and solution.

And yes, this is a two edged sword, and why initiatives like the Habitat solution surfaces. Complete freedom, unfortunately, also means you have complete freedom to mess up things. Badly.

To bring some concrete suggestions out; if you need a Database in your method or class, ask for it in the constructor or as a parameter. If you need a SiteContext, ask for it. Don't - please don't - try and configure a full Dependency Injection setup and abstract all of Sitecore into interfaces if this is your first Sitecore solution. It will cost you a LOT of time, much much more than you realise, and chances are no one will ever make back that investment of time in your first solutions lifetime. 

Yes, I really did just write that ;-)  Take my word for it. 

2c. Are you sure you need that event handler? And if you do, are you sure you're hooked into the right one?

Look, I'm pretty sure you don't need that item:Saved handler. Why?  Because the real need for them is so very rare. I can probably count on one hand, how many times I've needed to implement one over the course of 10 years of Sitecore development.

Chances are, you're trying to make Sitecore do something it shouldn't really do. This is actually a reference I wrote a blog post about years ago; Just because you can, doesn't mean you should. I'm going to rewrite this as part of this Decennial series, but for now the original post will have to do.

Take a step back; consider if what you're doing is really trying to solve a user training problem with a programming solution. Still need that handler?  Ok then.

Consider the context of your handler then. I often see examples, like an item:Saved handler that manipulates other items or possibly creates and re-creates parts of the Sitecore content tree, all based on a particular field value or something similar. Are you aware that item:Saved is fired as part of the PublishItem process?  (like when the published item is Saved to the "web" Database). 

Check your context, filter your context.

If you do implement handlers and processors, at least make sure they only execute when you expect them to. Check if item.Database.Name really matches the ContentDatabase, abort if it doesn't. Check that your bespoke ItemResolver code is currently serving content for the website you expect. "publishing", "shell", "scheduler" etc. are all websites on your solution, are you aware of that?

Consider these things, whenever you hook into anything. Be it item events, request processors, link managers or otherwise. 

As an example, look at the item:Saved handler that deal with keeping your LinkDatabase updated. (a hugely underestimated resource when it comes to Sitecore development, but this will be a subject for one of my next posts in this series).

    protected void OnItemSaved(object sender, EventArgs args)
    {
      if (args == null || LinkDisabler.IsActive || !Settings.LinkDatabase.UpdateDuringPublish && PublishHelper.IsPublishing())
        return;
      Item obj = Event.ExtractParameter(args, 0) as Item;
      Assert.IsNotNull((object) obj, "No item in parameters");
      LinkDatabase linkDatabase = ItemEventHandler.LinkDatabase;
      if (linkDatabase == null)
        return;
      linkDatabase.UpdateItemVersionReferences(obj);
    }

Notice how, the first statements in the event handler actually deals with asserting, if it should run at all. Sitecore makes no such determination for you, it is YOUR responsibility to ensure this.

This also goes for your PageMode.

2d. What is your current PageMode. Is it relevant?

Considering the current PageMode becomes important, when you're making run-time decisions that could affect the user experience.



Let's say you're putting in some code, to prevent your component from failing if it has been configured with a faulty Datasource. Or alternatively if you want to explicitly throw an Exception in that case, to help your fellow developers track down a bug.

Be careful. At site run-time (when PageMode.IsNormal) it could indeed be considered an error condition, if a component is configured with a Datasource that does not exist. This is quite likely NOT true for many of the other PageModes. Consider this:

An Editor is Page Editing (or Experience Editing, the new bling expression) inserts your component onto a page. What happens (simplified) is, that Sitecore adds your component to a placeholder key and renders it. You may or may not have a Datasource defined at this stage. Don't blow up. Don't YSOD. Your component is in a staging state, and your code needs to consider this. This is what PageMode is for. 

In general, I find it really bad form to YSOD on these specific conditions; like a missing Datasource or a reference field pointing to items that do not exist. Why?  Because it's very likely just User Error. An Editor forgetting to publish a related item (something that is VERY easy to do in Sitecore, even if the current publishing tools make this slightly easier). You really DON'T want to teach your users, if they make a mistake you're going to YSOD their site. You really don't.

Alternatively, if you can, discuss with your users what should happen. Either the component outputs some harmless content to alert them of this condition, or perhaps it hides itself completely. Again, only do this if PageMode.IsNormal or PageMode.IsPreview. Or maybe PageMode.IsDebugging, if you're using the Sitecore Debugger (you should). But consider it, don't just ignore it.



So I think that's it. For this post, anyway. Until next time :-)


Tuesday, January 12, 2016

10 years of Sitecore blogging – whereto now?

10 years of this blog and me (but probably mostly me)

So it all started in early 2006 with a post about IDTables (of all things…). I was a newly coined Sitecore Certified Developer, having recently left my “vanilla” .NET development consultant job to go work for one of the premiere Sitecore Partners and was now doing Sitecore full time.

As the blog posts of that time will testament, I was very much learning at the time. I was thrown straight into a rather deep dive, doing work that involved custom Data Providers, item proxying and in general trying to figure out ways to best integrate a lot of external data into Sitecore. Early versions of Sitecore 5 were… let’s use the word “challenging”, and Sitecore documentation and release notes were scarce, at best.

So yea; the first couple of years of blogging was almost entirely focused on sharing information that perhaps wasn’t otherwise apparent and openly discussing the direction Sitecore was taking on what I then believed to be a vitally important data integration features. These features are still important of course, but my view on this has become somewhat more nuanced over the years. More on this later.

Right around the launch of Sitecore 6, we’re talking 2008/2009 here, I had left the safety of employment behind and had started CorePoint IT Ltd – my 1 man Sitecore freelance/contracting company and was trying to work closely with the Sitecore UK office on helping out new Sitecore partners as they were brought into the fold. Sitecore UK was a very different entity those days, only a handful of people, working very hard to spread the Sitecore gospel to the British Isles.

“Yes, all fine and well, but how does that relate to this blog?”.  Well it does, see. Unlike today, there WAS no real market for Sitecore contractors back then. We were maybe a handful doing it, and LinkedIn did not have a constant flow of “Contract Requests” coming through on a daily basis.

So initially, I had a lot of time on my hands. I wrote what I believe to be one of the first ORM mappers for Sitecore – CorePoint Domain Objects; built a lesser known Ecommerce framework, and as my post count for 08/09 will show – wrote a lot of blog posts. It was all about visibility.

And it paid off, too. Work started coming in, to pay the almost extortionist London rent rates. I was awarded Sitecore MVP as one of the 10 first in the world and things were getting busy. So much so that I pretty soon found myself almost drowning in work and Sitecore services was coming in demand all over London (it was still predominantly London, at this time).

It also shows in my blogging activity ;-)   More posts were written in 2009 alone, than all remaining 9 years on this blog. As a contractor, one doesn’t get paid to blog (obviously) and while many bloggers today find time to blog on their employer’s dime, I have always been doing this on my own time. Time I take away from either work or (more often) family activities.

2010 through 2012 was “more of the same”. I went back to Denmark due to a family related issue, ended up staying almost 2 years working almost exclusively with Sitecore ecommerce related sites and solutions – architected yet another version of an ecommerce framework (based on ideas developed in 2008/09 and further refined here) – again being kept so busy, there was little time (or rather; energy) to focus on other things such as this blog.

2013 sees me back in the UK, this time outside of London. The market in London was now brimming with Sitecore contractors (though still not enough, by far) and my idea was to head out west – to Bristol – and service an area that was not well covered by other consultants. Not long after (but entirely unrelated, although I like to claim otherwise ;-)), Sitecore themselves opened up a branch office in Bristol. Excellent news, this also meant local Sitecore User Group sessions – and I remember the very first one I attended, was when Sitecore 7 was being presented.

Initially I get involved in yet more ecommerce on Sitecore with a local Sitecore client (as opposed to an agency) where I spent the better part of a year, but pretty soon thereafter it becomes apparent that the market “out west” isn’t all I had initially hoped. To keep work coming, meant I had to consider contracts pretty much all over the UK. That meant a lot of travelling, a lot of hotel rooms and you know… to be honest, it all became a bit too much.

I spend 2015 re-considering what I want to do with it all and by late 2015, having arrived at some conclusions, I make my biggest change yet and move to Switzerland. The German speaking market is massive; and there is currently quite a huge lack of qualified Sitecore developers and consultants – I figure I can keep quite busy here for years to come :-)

But enough about me.

Visitors and readers – Who are you?

Apparently, Blogger has decided to discard some of its data so unfortunately I cannot share with you the complete traffic numbers. Only data from the period "May 2010 – January 2016" is kept.

So who are you?    This blog doesn’t run on WordPress so I cannot do one of those fancy “You filled the Sydney Opera House 27 times over” type of posts. I do have some statistics to share with you however.

And it would appear, the vast majority of you are from the US, with United Kingdom and France as runners up. If anything, France being in the top 3 surprises me; I am unaware of France having a particularly high Sitecore adoptation rate. Looks like I could be very wrong on that :-)


All of this adding up to: “Pageviews all time history - 237,063” (again, since May 2010).

In terms of what posts you liked, 2009 seems to have been the absolute golden year with 6 of 10 posts in the top 10 coming from that year.


On a personal level it pleases me to see topics such a Sitecore migration at the top since this is one of the areas I would consider myself a specialist in. For some reason or other, I’ve just ended up doing SO many data migration projects with Sitecore over the years. Looking at this, I should probably schedule a few follow-up posts on this.

Also pleased to see some of my “recent” posts (and one from my friend and fellow blogger; Finn Nielsen) make it into this list. Gives me hope that this blog has more than just historical significance ;-)

There is also a statistic for traffic sources that I won’t even bother screenshotting and posting here. 97+% of traffic comes from Google referral, the rest comes from StackOverflow and a few forum posts on Sitecore Community Forums.

And whereto from here?

The next 10 years of this blog

10 years is a very long time. When speaking of Internet technologies it’s almost more than a lifetime. So no, I don’t actually know that I will be actively blogging and working with Sitecore, 10 years from now. What I do know, however, is that I expect to be.

What I also know, is where I want this blog to be heading in the time to come. 

In my opinion, for this blog to have any justified existence (or any blog for that matter), it must be focused on original content. To me this translates to less “How-to” content, and more “Why or why not?” content. If you take a quick look around the Sitecore blogosphere landscape today, the reasons for this should be obvious. 

When I started blogging in 2006 there was little to no documentation, and probably there were less than 20 of us blogging. If even 10. Blogging original content was a no-brainer. We were all working with pretty much a blank slate and there was so much to talk about.

Today, 10 years later, there are more Sitecore blogs than I know the number of. I used to follow them all on a blogroll (up until Google shut down Reader :/) – today this is (almost) impossible. Impractical, at least. Ironically this leads to the almost exact opposite situation as we had in 2006; it is becoming increasingly difficult to now find quality information on any particular Sitecore subject. Not because it isn’t there; there’s almost too much of it. 

So anyway. To stay relevant, I am going to take my 10 years of experience, over 20.000 billed hours of Sitecore consulting, and put myself out there and post (even more) opinions. The way I see it, opinions and practices I have formed on working with Sitecore over all these years are highly sought after by employers and agencies; surely these must have value to the readers of this blog as well.

So more “What does IoC and DI do to your development teams velocity?”, “What developer profiles make for good Sitecore developers?”, “The Content Release project milestone”, “How does Agile fit with your Sitecore development project?” – and less “Using Lucene and SOLR side by side with Sitecore Content Search”, “Load balancing your MongoDB setup”, “Multi-select dialogues with SPEAK 1.1”.

To be clear, there is absolutely nothing wrong with the “less of” examples I mention here. I just won’t be focusing on them; I believe we as a community are pretty well covered on those as it is.

To start things off, I will launch a project I have been working on for quite some time now. The “Sitecore Decennial Series”. What this is, is basically 10 posts each focusing on one aspect of Sitecore that in my opinion is key to success with Sitecore implementations. Not necessarily all from a developers perspective. Each post will be rather long – beware, those of you not into that kind of thing – and for this reason I am also going to set a realistic schedule for myself on these. The series will run over the course of this year, with a post every month – leaving 2 blank slots (TBD) which I hope to fill up with a bit of R&R and holiday time ;-)

Happy New Year everyone.

Saturday, November 30, 2013

Working with Page Templates

While keeping your Sitecore solution flexible

This blog post is part 4 in a series on “Creating good Sitecore solutions”. Rather than constantly going back and adding edits to the previous posts, just follow this link to get an overview of the series.

The story so far

By following the recommendations I’ve presented in this series, you’ll find yourself building a site that has little or no reliance at all on Page Templates. For starters, this is a good thing. Don’t worry about it.

By doing so, your solution stays on top of the Sitecore feature set – it can be personalised, conditional renderings can be swapped in and out and your marketing users can select winners of M/V tests and go about their business – just like intended. As I’ve argued earlier, the reason you are building this site in Sitecore at all over say… some of the competition… would be because of the distinguishing features of Sitecore. Not for the ability to build websites in Sitecore – I’m reasonably sure this can be accomplished in most competing CMS systems – but because Sitecore offers this great suite of tools surrounding it. The Sitecore Customer Engagement Platform or CEP.

Enabling your solution for these tools really comes down to this:

  1. Individual components on your site must respond to changing Datasource settings (configured by marketers, controlled by Sitecore)
  2. In the extreme, you as a developer really have no real say at all in what components end up on any given page. Marketers can, will and should perform testing of various component combinations on any given page and select winners accordingly. Sure, you can restrict this to some extent – but why should and would you?

All of which is fine, as long as you’ve implemented your components following the principles from this series of posts.

What then, do we use Page Templates for?

Having come this far, it’s probably time to take a look at what Page Templates then really should be, and how they can be used to make not only your life easier, but also that of your marketing users.

The first and most obvious thing that belong on your Page Templates, is “everything that isn’t really part of any component on your page”. Depending on how far your take your components, this could be things like:

  • Page description and keywords – for Google (if you still use these)
  • NOINDEX, NOFOLLOW checkboxes
  • Page titles (browser title, menu title and so on)
  • Page theme
  • Canonical URLs

In essence, anything that you would reasonably output as part of your Layout and Layout code. Data you will be pulling, at runtime, from Sitecore.Context.Item and where the concept of a Datasource makes no sense at all.

Fields like these, I tend to bundle up on a base template I name “Page” (appropriately), and all further Page Templates I implement will be inheriting from this. 

And what else?

You’re not going to like this answer. “It depends”. From this point on, what you choose to implement as Page Templates is up to you. I can tell you a few considerations you should have when deciding, and a few of the trade-offs you’ll be making however.

  • Are your marketing users accustomed to working with Sitecore?  And if they are, have they primarily worked with “traditional” Sitecore implementations, where pretty much all content sat on just one single item (a Page Template) in the Sitecore Content Editor?
    • If so, you should probably cook up a series of Page Templates for them. Fortunately, creating and altering Page Templates is now a much simpler task than it would have been otherwise, if you’ve followed the principles in this series of posts. I’ll demonstrate shortly.
  • Are there areas you are absolutely sure will not be subject of M/V testing?
    • I can tell you this; pretty much EVERY single time I’ve made a “judgment call” on this, I’ve been wrong. Sooner or later, once the marketing users really get into the spirit of really using Sitecore and working with their site, they will be wanting to M/V test the “strangest” things (and they should). All of these from real life, by the way.
      • The ordering of the main navigation menu
      • The naming for the “My Account” area
      • Placing the “left navigation” on the left and right side of the layout
      • Backdrop images for the site
      • “Sign in” versus “Log in” button text
    • Truth is, if your marketing users follow the spirit of continuously testing the site to improve conversion rate (and why wouldn’t they?) – every component is a candidate for testing
  • What about content pages that your marketing users create often?
    • Indeed the traditional candidate for Page Templates, and you probably should set up Insert Options for these
    • However keep in mind that the concept of Layout Presets. You could in reality just give your marketing users a set of insert options that all are simple inheritances of the “Page” template, with different presentation details on them or – alternatively - different Layout Presets
  • Large volumes of “page” items
    • Like an article repository or some such. Yes, you definitely should base these on a common Page Template. But that’s not the same as saying, you should necessarily have a tonne of fields on that template; you’re doing it primarily to have a single place to globally change Presentation Details for these pages.

What I’m getting at is this. Most of the reasons that I – and I suspect many – Sitecore consultants have set up Page Templates in the past, really came down to ease of managing Presentation Details for a given page type. So we’d have a lot of content in the solution, say 1000s of “News Article” items for instance. And then along comes a marketer, wanting to show the “Spring Sale” banner on the top of all of them. No problem; find the “News Article” template, edit the Standard Values Presentation Details for the template and you’re done.

The less common scenario – but quite challenging if you’re following the “old ways” would be; marketing user comes along and wants to replace “Component XYZ” on the “News Article” pages with “Component ZYX”. The two components are not alike in any way, and use completely different fields.

Sure, part of the challenge is easy enough. You go to the “News Article” template Standard Values, you swap the components around. But what then? Do you then change the inheritance of “News Article” so it includes the fields required by “Component ZYX”?   You would have to, unless it was implemented following the principles of these posts – always respecting it’s Datasource, and being based on a known Datasource Template. If it doesn’t, you’re out of luck.

So you proceed and change the inheritance of “News Article” – you put in some default values on the Standard Values item for the template. The rest… well that’s up to the marketing users. There’s 2 problems left lingering here:

  • What about the fields being used by “Component XYZ”?  If you’re lucky, you know exactly what they are and you can proceed to remove them from the “News Article” template. Let’s just hope the fields are not being used by other components on the page
  • Your marketing users can’t edit Standard Values. If the default values you configured need to change, they would need to come to you to get them changed – alternatively manually edit the 1000s of pages (and this, they won’t be happy about)
  • Ok so there’s 3 problems. What if “Component ZYX” really needed a different set of values based on where in the content hierarchy the News Article resided?

No matter your approach, none of this is truly ideal. Having fields on Page Templates is a compromise in pretty much any way you look at it. Both in terms of flexibility and what you can do with the site, but also how you make changes to it going forward.

But if you really want to, here’s how easy it is to make and amend Page Templates following these principles

Having said all of the above, you will still be doing Page Templates. Especially if you’re dealing with marketing users who’ve never known Sitecore to be anything else than the Sitecore Content Editor interface, never did an M/V test in their life and don’t plan to. My own opinions aside; these absolutely do exist. Cater for their current needs, but don’t bar them from moving forward using Sitecore.

Fortunately, this is now easier than ever. Say I have a page like this.

30-11-2013 12-53-13

As shown in my previous posts in this series, this just sits on a very basic “Page” template with no fields on it. All of the components are implemented following these practices, they respect the Datasource given and will fall back to Sitecore.Context.Item if no Datasource is provided for them.

Presentation details for this item looks like this:

30-11-2013 12-56-03

And here’s the item as shown in Sitecore Content Editor

30-11-2013 12-57-36

Let’s then say that I want to make some of the components part of the template for this page. Header and the Top Menu. No problem at all, I go to the Site Root template I’ve set up for this page. This becomes even easier if you have a snapshot of your presentation details showing on the screen.

30-11-2013 13-02-19

The icons you’ve configured for your Datasource Templates help you here. Having done this change, my Home item now looks like this.

30-11-2013 13-04-43

So far, nothing has changed on my site. The presentation details for my components on this page still point to the Datasources I have configured. To change this, I need to then go to my Standard Values for the Site Root, and clear these fields. While I’m there, I set up fill in some Standard Values content on my new fields.

30-11-2013 13-08-25

I clear the Datasources for the components I’m now making part of my Page Template

30-11-2013 13-09-33

And after a quick publish, the site now looks like this.

30-11-2013 13-14-10

For all intents and purposes, my Home item now looks and acts like it was created using traditional “Page Templates”, but I retain the confidence that I can make amendments to this structure easily. The components can still be tested and swapped around and so on – but my marketing users can still keep using the Sitecore Content Editor to work with my “Page”.

For those of you who read my previous post in detail, I would actually normally
choose the DatasourceOrSiteRoot strategy for things such as
the Header component, but that’s not really relevant in the context of this post.

You can, of course, add as many base templates to your Page Template as you desire – for a full blown “Sitecore Content Editor” experience. Remember I said in a previous post; you’re not really building designing your information architecture in the manner I lay out in these posts only to cater for the Page Editor users?  Well this is it – you do it for your Content Editor users as well. And your solution will be better off for it, for both types of users.

And you’ve still not incurred any cost!

I stand on my argument made in previous posts; building up your information architecture in this manner from ground up adds no cost to your implementation.

And I can honestly say, making and amending Page Templates has never been easier. Making them becomes as easy as just identifying which components on the page you consider to be “always part of the page” (and disregarding what I said above; in reality you risk making the wrong judgment call on this) – and make your Page Template inherit from the respective Datasource Template templates.

By doing this; everything still works “as before”. But you now have the certainty (because you’re components are done right) that you can make amendments to this decision in the future. And yes, everything on the page can still be personalised and tested(!). Yes it really can; setting up a test is as simple as defining the test variations (this, your marketing users would need to do in any event) – and setting them up. Default would just be the blank Datasource.

M/V testing when using Page Templates

Set up the variations. I suggest creating a folder with a meaningful name, so you can later do a bit of cleanup and get rid of the losing variations.

30-11-2013 13-46-51

Set up the test, as you normally would.

30-11-2013 13-49-53

And you’re good to go. Your problem only comes, when a winner is selected. This problem is inherent to Page Templates. Consider this:

The test runs, and ultimately the marketing user will select Variation B as the winner. What Sitecore will do is this; it will change the presentation details – so that the Datasource for the Header component gets set to Variation B. And this is fine – if your component is done right, the site will now be showing Variation B whenever rendering the Header component.

Only problem is; you’re still stuck with fields on your Page Template that now no longer hold any meaning. The Header fields on your Page Template are not being used and only act to confuse your marketing users. At least the ones who use the Sitecore Content Editor; in Page Editor everything will still appear normal.

Out of the box, Sitecore does not directly offer any solutions to this problem. Personally, I try and avoid Page Templates as much as possible. Fortunately there are several things you can do to solve this; easiest being to just go to your Site Root Page Template and remove the Header inheritance – fields will be gone and the world moves along. I’ve also seen a number of blog posts recently (although a specific one fails to come into memory right now) that deal with ways of hiding fields from the Content Editor for various reasons.

Making changes to Page Templates

Not really any different than before, but you do have a few more options available to you if you’ve followed the practices laid out in these posts.

In the example from above, you could also choose to just add your new “Component ZYX” to the Presentation Details of the Standard Values item and have its Datasource point to somewhere in your content repository where the marketing users can reach it. That way you avoid the problem of restricted access to Standard Values entirely.

And what if you had to solve the problem, of changing the content of “Component ZYX” based on where the News Article resided in the content tree?   Still not a problem; personalise the component using the Sitecore Rules Engine – like this for instance:

(I don’t have a Component ZYX, so I’ll pretend my Header component is it)

30-11-2013 14-17-47

Easy, but not so easily achievable had you been using the traditional Page Template approach. Or as I’d also like to put it; had you made The Page Template Mistake.

In summary

This will be the last post in the series “Creating good Sitecore Solutions”, but it will not be the end of what I have to say on this subject – not by a long shot. Everything I write about is based on my personal experiences, and I do follow the practices in these posts in my daily life as a Sitecore Consultant / Architect. I will keep posting about the experiences that come from this, and I also have a few tricks up my sleeve for solving some of the common issues that might arise, when working in the manner described here.

There are a few pitfalls, I’ll be the first to admit. But I’ll quickly add to that; the pitfalls I’ve encountered using this approach are by far less and fewer, than the problems I’ve been in when using Page Templates and components that clinged to them.

I hope – if nothing else – that the series has inspired a few new ideas out there :-)

Thursday, September 05, 2013

Working with Component / Data Templates

Avoiding the Page Template Mistake

This blog post is part 3 in a series on “Creating good Sitecore solutions”. Rather than constantly going back and adding edits to the previous posts, just follow this link to get an overview of the series.

A few thoughts

As promised in my last post; The Page Template Mistake; I will now attempt to put my money where my mouth is (so to speak) and provide something more concrete as to how the Page Template Mistake can be avoided, and how your implementation might carry forward without encountering it.

Before I do however, I will just clarify a few things that perhaps got lost in the previous posts.

I do believe that there is a time and a place for Page Templates. It just follows much later in the process and is a much more dynamic entity than what was certainly the case for my own solutions. I would not recommend content editors being forced to add any and all components to a blank “page canvas” for every page they create – we have Page Templates, Layout Presets and other technologies to help them out here.

What I advocate is, that you move the entire consideration of Page Templates much much further back in the process. Move it to the very end. Both to help you verify and assess components as the project comes about (if you’re tasked with that role), but also to help developers break free of the Page Template mindset entirely.

Your project will be better off for it.

My next post will be coming full circle, and demonstrate how Page Templates can be set up once you have all your Component Templates in place and – and I feel this point is important, because this used to be such a hassle for me in the past – how you can easily and quickly mock up new Page Templates as the situation requires, without breaking a sweat of what might break. Think yellow screens, think “Object Reference Not Set…” – all the common mishaps that you’ve experienced when tossing components onto a newly set up Page Template in the past.

Lastly; You’re not doing this specifically when “designing for the Sitecore Page Editor” as a few have suggested. That is a misunderstanding. What I am suggesting here is an approach that you would be taking if you’ve decided to make a good Sitecore solution. That it also happens to be a prerequisite for most meaningful work in the Sitecore Page Editor is consequential and accidental, you should not set out to “design for the Page Editor” at all.

After all – in doing so – you are inferring that this is a specific task, possibly an extra task. It is not. What I am suggesting is cost free, adds no overhead to your project. If done up front, that is. If you start by deciding to build a good Sitecore solution.

And on that note, let’s get to it.

Implementing a Component Template

To serve as an example, I’ll pick a component from the – in theory – up and coming CorePoint IT website (my own one-man consulting company). I say in theory because just as the mechanics own car, somehow working on this website always seems to end up fairly low on my priority list ;-)

I’ll pick something simple to start off with. In the HTML I’ve had done for the site, it looks like this:

04-09-2013 19-13-20

Looking at the HTML snippet for this component, it looks like this.

<div id="topBanner">
    <img src="images/banners/glass.gif" alt="" />
    <div id="topBannerContent">
        <h4>The company that does anything...</h4>
        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.</p>
    </div>
    <a href="#">Read more >></a>
</div>

No big surprises there. Not too happy about the “id” attributes in there but let’s set aside that discussion for the time being.

I identify 5 tokens (tokens is a bad term. Anyone have another suggestion?) in there that I would like to see content managed on this component.

  • Heading
  • Body Text
  • Image
  • Link Text
  • Link

Breaking up the link near the bottom into two separate entities is a habit I’ve adopted. While it is possible on a Sitecore “General Link” for content editors to specify things such as Link Text; this doesn’t hold true for “Internal Link”. Doing it like this as a convention just saves a lot of grief.

Setting up the Component Template

04-09-2013 19-34-45

While this may look apparent, there are quite many (of my own) conventions in play here. I recommend you follow them, each of them will grant you “+2 to the overall Sitecore goodness feel”.

  • Give your component a good name. As “good” is subjective, here’s a few examples of component names that are NOT good (all of them from real life):
    • phInnerHeadingBox
    • HeroBoxTopRight
    • Content Spot
  • Set an icon for your Component Template. First thing, no delay. And while you can try and be creative and find an icon that “matches what your component does”, you will likely fail – the icon set is too generic for that. Don’t worry though, as it doesn’t really matter WHAT icon you choose – just that you choose one, and choose the same one in the steps to follow.
  • Place your fields in one “Section” named in exactly the same manner as your component.
  • Assign the icon from above, to that Section as well. Here’s how:
    04-09-2013 19-43-12
  • Name your fields, prefixed with the Component Name.
    • This is controversial, I know. But given that Sitecore does not distinguish Sections when addressing fields, and you cannot make any assumptions at this stage about the Page Template that your component will be living on (since you don’t know, and never will) – doing it like this provides the Path of Least Surprise later on.
    • Also keep in mind; field names mean nothing (really) when your content editor user is in the Page Editor – and given that the same user is given the context via the Section in the Content Editor, they won’t have much trouble scanning the fields for the one they need there either.
  • Set a short help text for each of your fields. This often overlooked step will mean a world of difference for your Content Editor users, takes you about 10 seconds per field (at this stage in the process) and grants you “Sitecore goodness” karma. If you haven’t done this before – try it. Take my word for it. Here’s how:
    04-09-2013 20-04-21

And you’re done. For now.

Setting up the Component

Proceed with your method of choice to set up the Sublayout Component in Sitecore. (Covering everything involved in this step probably could use a blog post of it’s own. I deem this out of scope for this one). Name it the same as your Component Template.

04-09-2013 20-11-03

Carry out these steps:

  • Set the icon for the Component to the same icon you chose for the Component Template.
    04-09-2013 20-13-34
  • Set the Datasource Template to your Component Template.
    04-09-2013 20-14-59

    04-09-2013 20-16-04
  • Finally take a snapshot of your component, and set up the Component thumbnail.
    • If your Component is part of a multi-site solution and look completely different between the sites, leave out this step. Sitecore requires customization to be able to do site-specific thumbnails, something I might cover in a later post. Tweet if you want it. @cassidydotdk ;-)

      If there is no thumbnail defined, Sitecore will show an enlarged version of your chosen icon for the component when adding it in the Page Editor. Not ideal, but still sticks with the established convention pretty good.
    • Set it up like this.
      04-09-2013 20-28-44

And that’s pretty much it. There may be additional things to consider when setting up your Component; Rendering Parameters and so on – I’m going to skip that for this post, as it doesn’t lean towards the points I am making here. I know I say that a lot, but hey… this post is going to be more than long enough already.

Implementing the Component

Like a TV chef, I’m going to skip ahead quickly and show you the resulting Sublayout .ASCX. The layout I’ve created does nothing but set up one Placeholder; “content” and include the relevant CSS files. For those of you riding the MVC wave, I’m sure you can adapt.

The .ASCX
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Top Banner.ascx.cs" Inherits="Website.layouts.CorePoint.Top_Banner" %>
<div id="topBanner">
    <sc:Image runat="server" Field="Top Banner Image" ID="sciImage"/>
    <div id="topBannerContent">
        <asp:PlaceHolder runat="server" ID="phHeading">
            <h4><sc:Text runat="server" Field="Top Banner Heading" ID="sctHeading"/></h4>
        </asp:PlaceHolder>
        <sc:Text runat="server" Field="Top Banner Body Text" ID="sctBodyText"/>
    </div>
    <asp:PlaceHolder runat="server" ID="phLink">
        <sc:Link runat="server" Field="Top Banner Link" ID="sclLink">
            <sc:Text runat="server" Field="Top Banner Link Text" ID="sclLinkText"/>
        </sc:Link>
    </asp:PlaceHolder>
</div>

The codebehind is empty, at this point.

Creating a Data Item based on my Component Template

I then create an item, based on my newly created Component Template.

04-09-2013 21-27-47

And to further stress my point that Page Templates have no place at this point, I will just proceed to modify the presentation details of the default /content/home item that ships with Sitecore.

Setting up the Sitecore page

I change the presentation details for the item, to look like this. As mentioned; the Layout only holds the basics – and a placeholder keyed “content”.

04-09-2013 21-31-04

And finally I configure my Top Banner component to use my newly created Content Item as a datasource.

04-09-2013 21-32-58

After all this, I do a quick publish – and this is what I see. If I hadn’t read The Page Template Mistake or John Wests post on how to apply data sources to components, I might be surprised at this point.

04-09-2013 21-38-01

Nothing shows. Your first instinct might be to have a look at the page source. It looks like this.

04-09-2013 21-39-34

So essentially; the component gets rendered ok. There’s just nothing in it.

And this is the crust of the Page Template Mistake. Sitecore does nothing (for you) to respond to your configuration; setting the datasource to your content item. And I do believe this is the first reason many venture down that mistaken road and begin making the Page Template Mistake in the first place. There is no immediately obvious way to get to the datasource, and the standard Sitecore web controls don’t respond to it. So one retorts to hitting the Sitecore.Context.Item, and from here on out your fate is sealed.

Fortunately there’s a better way to approach this. Let’s introduce a bit of codebehind.

Implementing the Component code (basic)
public partial class Top_Banner : UserControl
{
    protected Item _actionItem = null;

    public Item ActionItem
    {
        get
        {
            if ( _actionItem == null )
            {
                var sl = Parent as Sublayout;
                if ( sl != null )
                {
                    if ( !string.IsNullOrEmpty( sl.DataSource ) )
                    {
                        Item datasourceItem = Sitecore.Context.Database.GetItem( sl.DataSource, Sitecore.Context.Language );
                        if ( datasourceItem != null && datasourceItem.Versions.GetVersions().Any() )
                            _actionItem = datasourceItem;
                    }
                }
            }

            if ( _actionItem == null )
                _actionItem = Sitecore.Context.Item;

            return _actionItem;
        }
    }

    protected void Page_Load( object sender, EventArgs e )
    {
        sctHeading.Item =
            sctBodyText.Item =
            sciImage.Item =
            sclLink.Item =
            sctBodyText.Item = ActionItem;
    }
}

And the result.

04-09-2013 23-42-10

This is more or less Datasource 101. Implement like this, and you are more or less imitating XSL Renderings and how $sc_item is set up to work by default.

Look here’s the thing:

If you do this, and you do it consistently, your solution is already in the top N percent of well implemented Sitecore solutions. Good solutions. DMS enabled solutions. Almost by default.

You can work your way up from here, and I will give a few examples of that. But it starts here. It starts by deciding that what you want to do, is build a good Sitecore solution. You could do nothing more than just this in your solution, and you’d have pretty much all DMS scenarios covered. I really am not kidding.

Just one gotcha; Sitecore 7 expands upon the Datasource concept. Since I am blogging in the context of personal experience and practices I myself have found to be successful – I cannot account for how the above code fits with Sitecore 7. I have no live sites under my belt at this stage that uses Sitecore 7. My initial guess would be; “it’s probably fine” however.

Implementing the code (intermediate)

The next natural step up from here would be to push the ActionItem code to a base class, and make all your Components inherit from here. Quite many of my readers of the previous posts in this series point this out – and until recently this has also been my own sole approach to this problem.

The base class could look like this.

public class BaseSublayout : UserControl
{
    #region :: Action Item ::
    protected Item _actionItem = null;

    public Item ActionItem
    {
        get
        {
            if (_actionItem == null)
            {
                var sl = Parent as Sublayout;
                if (sl != null)
                {
                    if (!string.IsNullOrEmpty(sl.DataSource))
                    {
                        Item datasourceItem = Sitecore.Context.Database.GetItem(sl.DataSource, Sitecore.Context.Language);
                        if (datasourceItem != null && datasourceItem.Versions.GetVersions().Any())
                            _actionItem = datasourceItem;
                    }
                }
            }

            if (_actionItem == null)
                _actionItem = Sitecore.Context.Item;

            return _actionItem;
        }
    }
    #endregion

    protected void ApplyActionItemRecursively()
    {
        var ai = ActionItem;
        foreach ( Control c in Controls )
            RecurseControls( c, ai );
    }

    private void RecurseControls( Control parent, Item actionItem )
    {
        if ( parent.GetType().FullName.StartsWith( "Sitecore.Web.UI.WebControls" ) )
        {
            var itemProp = parent.GetType().GetProperty( "Item" );
            if ( itemProp != null )
                itemProp.SetValue( parent, actionItem );
        }

        foreach( Control c in parent.Controls )
            RecurseControls( c, actionItem );
    }
}

And with this, every one of your components would look like this in their basic form. This is where my claim “this adds no cost to your solution”. I’ll say it again; implementing Components this way carries no significant overhead. You set up this base class once, and that’s it.

public partial class Top_Banner : BaseSublayout
{
    protected void Page_Load( object sender, EventArgs e )
    {
        ApplyActionItemRecursively();
    }
}

All I have left to do, is a slight bit of housekeeping. This is another convention I apply and if you stick to it, I am fairly confident your content editor users are going to love it.

public partial class Top_Banner : BaseSublayout
{
    protected void Page_Load( object sender, EventArgs e )
    {
        ApplyActionItemRecursively();

        if ( string.IsNullOrWhiteSpace( ActionItem[ "Top Banner Heading" ] ) )
            phHeading.Visible = false;

        if ( string.IsNullOrWhiteSpace( ActionItem["Top Banner Link Text"] ) )
            phLink.Visible = false;
    }
}

And that’s it, essentially. The Component is done. It’s well behaved, it can be used in M/V tests – call it “DMS Enabled” if you must. And if all your components are implemented in this manner, your life when creating Page Templates later on will be a heck of a lot easier. Painless is more like it. And it never cost you a dime.

For that, however, you are going to have to wait for the next post in this series.

You can stop reading now :-)

But for those persistent enough to make it this far in an already excessively long post; I’ll demonstrate where I am currently at myself in my pursuits of a mythological “best practice” in this area. I will be brief and post mostly code with minimal commentary. If you’re at this level of Sitecore implementation experience, I’m sure it will make sense.

Implementing the code (advanced)

The problem with the above approach is of course, as many commenters have pointed out. In real life, not all components fit nicely into this pattern. Sitecore themselves sort of indicate this as well; every default XSLT rendering has a $home variable defined (albeit commented out). Sometimes applying “Datasource or Context Item” just isn’t good enough.

Think Headers and Footer Components for instance. While you likely could be implementing a Datasourced Header component on one of your (deep) base templates, for many purposes this just isn’t practical.

Mark Ursino rightly mentions this problem in a comment;

“Global information (e.g. header and footer) cannot really be componentized too well unless you use standard values on a very low level "base page" template to assign the same header and footer data source items to all pages. I typically instead just define a predefined structure in a global area to support the header and footer.”.

Mark, I’m with you here, but I still believe that any component that “breaks out” of the imaginary “bounding box” that is its Component Template is creating an anti pattern in the solution – not unlike how Global Variables do it for traditional structured programming.

And there’s likely many similar scenarios.

Fortunately this can be resolved easily as well – without tweaking much in the code I just presented. AND – and this is important – without starting to make up a “meta CMS in the CMS” by adding global configuration structures and similar. I’ve taken this approach myself, and I always found them to be inhibiting me sooner or later in the lifetime of the solution.

Here’s what I suggest.

Have your components adhere to relevant strategies for resolving the ActionItem. Mostly – what I just lined out above will be fine. For some components, it would be more appropriate to EITHER respond to the Datasource (if set) or retort to $home. For others again; perhaps responding to Datassource (WHATEVER else you do; always always always respect the Datasource if one has been set. Always. Please. Having a “global header” that cannot be datasourced to make a quick micro-site is just a right pain) and retorting to crawling “up the tree” until you find an item that inherits from your Component Template.

It looks like this. I’ve abbreviated slightly. It’s going to be a long paste, so I’ll quit writing now and just let the code do the rest of the talking (mostly).

Until next time :-)

namespace Website.layouts.CorePoint
{
    public abstract class ActionItemStrategy
    {
        public abstract Item Resolve( Control c );
    }

    /// <summary>
    ///     Classic Datasource handling
    /// </summary>
    public class DatasourceOrContextItemStrategy : ActionItemStrategy
    {
        private Language _fallbackLanguage;

        public DatasourceOrContextItemStrategy( Language fallbackLanguage = null )
        {
            _fallbackLanguage = fallbackLanguage;
        }

        public override Item Resolve( Control c )
        {
            var sl = c.Parent as Sublayout;
            if ( sl != null )
            {
                if ( !string.IsNullOrEmpty( sl.DataSource ) )
                {
                    Item datasourceItem = Context.Database.GetItem( sl.DataSource, Context.Language );
                    if ( datasourceItem != null && datasourceItem.Versions.GetVersions().Any() )
                        return datasourceItem;

                    if ( _fallbackLanguage != null )
                    {
                        datasourceItem = Context.Database.GetItem( sl.DataSource, _fallbackLanguage );
                        if ( datasourceItem != null && datasourceItem.Versions.GetVersions().Any() )
                            return datasourceItem;
                    }
                }
            }

            return null;
        }
    }

    /// <summary>
    ///     Resolves the ActionItem by datasource and falls back to Site Root.
    /// </summary>
    public class DatasourceOrHomeItemStrategy : ActionItemStrategy
    {
        public override Item Resolve( Control c )
        {
            Item datasourceItem = new DatasourceOrContextItemStrategy().Resolve( c );
            if ( datasourceItem != null )
                return datasourceItem;

            Item home = Context.Database.GetItem( Context.Site.StartPath, Context.Language );
            if ( home.Versions.GetVersions().Any() )
                return home;

            return null;
        }
    }

    public class BaseSublayout : UserControl
    {
        protected Item _actionItem = null;

        public Item ActionItem
        {
            get
            {
                if ( _actionItem == null )
                {
                    _actionItem = GetActionItemStrategy().Resolve( this );
                    if ( _actionItem == null )
                        _actionItem = Sitecore.Context.Item;
                }

                return _actionItem;
            }
        }

        protected virtual ActionItemStrategy GetActionItemStrategy()
        {
            return new DatasourceOrContextItemStrategy();
        }

        protected void ApplyActionItemRecursively()
        {
            Item ai = ActionItem;
            foreach ( Control c in Controls )
                RecurseControls( c, ai );
        }

        private void RecurseControls( Control parent, Item actionItem )
        {
            if ( parent.GetType().FullName.StartsWith( "Sitecore.Web.UI.WebControls" ) )
            {
                PropertyInfo itemProp = parent.GetType().GetProperty( "Item" );
                if ( itemProp != null )
                    itemProp.SetValue( parent, actionItem );
            }

            foreach ( Control c in parent.Controls )
                RecurseControls( c, actionItem );
        }
    }
}

And with this in place, the individual Component implementations could “do nothing” – in which case they would just apply default behaviour. But for some cases, overriding this behaviour is desirable – so we configure these with simple overrides. A few examples.

Site Header Component
protected override ActionItemStrategy GetActionItemStrategy()
{
    return new DatasourceOrHomeItemStrategy();
}
Implementing Language Fallback

Make this your default sublayout, overriding the default I listed above.

protected override ActionItemStrategy GetActionItemStrategy()
{
    return new DatasourceOrContextItemStrategy( Sitecore.Globalization.Language.Parse( "en" ) );
}

Make up your own as you go along. Not too many though – or the point of this whole exercise gets lots completely. I can attest from experience however; just the two first strategies solved the very large majority of my component worries. And I don’t implement any meta-structures any longer to support neither menus, nor headers or footers, or pretty much anything else for that matter.

And the flexibility this approach gives me in setting up any and all Page Templates that my content editors require; is near phenomenal. More on that next time.