Page Provider - Structure your site
There might be occasions where you like to have a view of your site structure that is different from the "real" structure. Perhaps you like to view only pages in a specific language, pages that you have written, pages with some specific category, pages filtered by some criteria or pages listed in some other structure like alphabetical.
You can use page providers to create "virtual" strucures that complements or replace the "real" structure. This makes it possible to have the same page appearing at several locations in the overall strucure.
Below is a screenshot from a little test implementation I done (code is attached below). In the tree you can see pages "Category pages", "english" and "My Pages" that are EntryPoints to page provider instances. The pages these providers provides though are internal EPiServer pages that are present in "ordinary" structure as well. "Category pages" list pages with a specific category, "My pages" lists all pages the current user has written while "english" lists the ordinary tree but filtered to show only a single language.

Apart from using this in edit mode as an alternative structure you can also use this in view mode for e.g. binding web controls to the "virtual" nodes, meaning you can e.g. create navigational controls that has another structure than the ordinary site structure.
There are two different options on how identities can be handled:
Keep identity - In this case the page provider simply return pages and page references as they are returned from default page provider. The links rendered for this pages will simply point to the original page, so if someone e.g. click on a virtual page in edit tree (or view mode) they will be redirected to the original page. In this case there will only be one version of the page in the page cache.
Map identity - In this case the page provider will change the PageLink and the PageGuid for the page before it is returned. Then the links will be rendered to the "virtual" page and it will then be possible to navigate within the virtual structure. In this case there will two pages in the cache, the original page and the "virtual" page.
Below is examples of how links will be rendered for the two cases. In the example entrypoint "en" above is shown in view mode:

There are some things that has to be considered when using this techinque with virtual structures:
- When to invalidate caches? By default will pages and child listings from page providers be cached. It is up to the provider to set correct cache dependencies. If you map ids then each virtual page should probably have a cache dependency to the original page. For child listings it might be trickier to know when to remove the listing from the cache. This really depends on how you collect the virtual children.
- Circular references: In the case you do not map ids you must make sure the page provider does not return any page that is any ancestor to the entrypoint. This would otherwise lead to infinite recursion in GetChildren.
- Links to virtual pages? If you use id mapping and want to support that it should be possible to link to a virtual page then you have to make sure the virtual page gets the same Guid based identifier each time it is loaded (e.g. when application restarts). This can be achived either by persisting a map table somewhere or have a algorithm that generates the same id every time. (There is a sample of a simple implementation of the later in the code sample, a class called PredictableGuidMap).
The sample code is developed against a version later than the released R2 version but it should compile/work against R2 version. The code is written as test/sample code and as such it is not of production quality, there is e.g. no proper error handling etc.
Source code
05 December 2008