Back in the day when we started designing our last project weâve been presented with a following problem â a big number of templates with slightly different sidebars.
HmmâŚ
Is sidebar a part of content? No, rather not. We donât want the editors to have to setup the sidebar for every article they write (and the site has a few dozens of articles created on it every day).
Is sidebar more of a template thing? Well⌠more like it, but still⌠we have articles all over the site with different sidebar elements when the articles are in different parts of the site (ok so we could add rules what controls display in which part of the site). But wait! Thereâs more! The sidebar will be different for every language (region). Now weâre talking a dozen of templates or a rules engine just to make the sidebar different. Customising the template with properties isnât ideal either as it makes EPiServer UI very cluttered. Additionally we want to change sidebars across many templates so the whole branch/section of the site will be able to share the same sidebar.
To a degree this is an academic discussion as weâve been through it with the previous version of the site and we already knew that integrating this stuff into templates just wonât work and we will be in a world of pain just changing the templates over and over adding little tweaks and changes while the customer ads promotions and performs ad campaigns. Well, we can do it, of course, but itâs not a work a programmer will enjoy, and we all want to do new and more exciting things, donât we?
We have an internally developed module to make something like that, that is fully home-grown by another internal team (we now have 3 âsquadsâ capable or making incredible things with EPiServer and we tend to share a lot of technologies and try to rotate people around to adopt the good habits and experiences) and I was (and still am) VERY impressed by it. The technology uses EPiServer pages for defining every module (which are located somewhere outside the site root branch. and then you can mix and match them either declaratively in the code) or by handpicking them in the UI. Itâs really cool, though, during the discussions it turned out that we might have to add big chunks of functionality and might end up with separate branches of module-pages for different languages/regions, but⌠frankly⌠about that time an article by Ted Nyberg reminded me about a technology I have read about quite a while ago in an article by Stein-Viggo Grenersen and ooohhhhhh⌠I got seduced. I really wanted to try if for a long time and Tedâs article made it a snap to try and get convinced, and more important⌠convince Stu ;) that itâs the right way to explore.
So I started to dig.
Talked with Steve (the original creator of the Framework) a bit and learned that I can âcustomize a path rewriterâ to suit my needs. Great! I just hoped I wonât have to deal with some nasty GUIDâs matching, but no! Turns out, all it takes to identify a WebPart set is to have any unique string naming it.
So basically what we needed was a manager to deal with the naming templates and a way to determine the WebParts set to be used per page.
Till now the framework used template file name followed by the page ID, followed by an eventual language/region if a page was not the master branch, for example:
~/templates/Demo/WebPartPage.aspx|26
~/templates/Demo/WebPartPage.aspx|26|en-us
which makes them unique per page, which is not as appealing when you use EPiServer as it for a big part duplicates its functionality. Also a bit of a caveat here for agile programming methodology which promotes an often and early refactoring â if you move your page around or change its name â you lose the WebParts for all pages using it.
What we needed is a flexible and extensible scheme for reusing âWebParts setsâ and thatâs what our extension allows for.
Also since weâre very performance sensitive, and we operate in a multi server scenarios a lot weâve added web parts blobs caching. Meaning that the site does not have to reach to the database every time a page is rendered.
The very appealing side of the framework is that it can be extended form the bottom (persistence) from the top (editors, controls, webparts), as well as being pluggable with custom plumbing.
The Sidebar Extensions for WebParts Framework
So to put all the requirements together, we needed the sidebars to be:
- customizable (out of the box)
- easy to use for both developers and editors (out of the box) Wow Steve, I canât really appreciate enough how cool it is to code for it and how nice it is for the users!
- localizable
- reusable
- inheritable for site branches
WebParts path patterns
The main idea was to free the path names from the restriction they had â being hardcoded for a page. So to do it without hard-coding them Iâve introduced path patterns.
What is a pattern?
Basically a pattern is a way the framework is supposed to encode the WebParts id for the system to identify. Your site can have any number of ânamed patternsâ and the framework gives you means of switching between them. Pattern allow for almost any string to be a part of it although some tokens have special meaning:
Token | Replacemnt Value |
%pageid% | id of the page the path is formed for |
%region% | language/region of the WebParts |
%pagetypeid% | type of the page |
%template% | legacy token to make it possible to use template names as part of path. This is just for compatibility so you can have some of the pages using an old scheme. |
%legacyregion% | legacy token for regionalizable pages (usage described later) |
%inherited% | states that a page shoud inherit its WebParts from its parent in the page hierarchy (this can only be used as a complete pattern â cannot be a part of a larger pattern) |
%root% | (again whole pattern) the %root% token is used when the inheritance based on hierarchy does not resolve into another token while reaching the root page. |
Some sample patterns
Name | Pattern | Sample Instance of the Pattern | Description |
Root pattern | %root% | %root% | The pattern that all inheritance automatically falls back to |
Inherited | %inherit% | anything parent defines | Tells the page to use the web parts its parent is using â the inheritance is possible all the way up in the hierarchy to the %root% pattern, meaning â if my parent inherits its WebParts from its parent, so will I. |
Legacy regionalized | %template%|%pageid%%legacyregion% | ~/templates/Demo/ââWebPartPage.aspx|26|en-us | Creates legacy ânon language independent pathâ |
Legacy global | %template%|%pageid% | ~/templates/Demo/ââWebPartPage.aspx|26 | Creates legacy âlanguage independent pathâ |
Page/region specific | page|%pageid%|%region% | page|26|en-us | template independent per-page/per-language pattern |
PageType specific | pagetype|%pagetypeid% | pagetype|5 | page type specific path (notice how the previous pattern has âpageâ and this one has âpagetypeâ in it) â this is done to avoid conflicts in numbers between pages and page types of the same id |
My Sidebar | my-sidebar | my-sidebar | You can create ânamed setsâ that will stay the same across all pages using it |
My Localizable Sidebar | my-sidebar|%region% | my-sidebar|en-us | A localized version of the previous ânamed setâ |
This entry (Permalink) was posted on Thursday, January 8th, 2009 at 3:04 pm and is filed under .Net Framework, ASP.NET, C#, Downloadable, EPiCode, EPiServer, Internet Information Services, Open Source, Software, Software Development, Web applications, WebParts. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response , or trackback from your own site.