Mapped Page Provider

by: Allan Thræn

UPDATE 2009-11-02: This code for this project has now been moved to CodePlex.


Until now, my favorite new feature in EPiServer CMS 5 R2 is the ability to attach custom page providers (http://labs.episerver.com/en/Blogs/Allan/Dates/112230/8/Building-your-own-Page-Provider-Northwind/http://guides.episerver.com/smartass/players/guideplayer/GenerateGuideHTML.jsp?Guide=http://guides.episerver.com/smartass/media/20081113/37/Guide.xml). It’s truly awesome to be able to connect any kind of external data source to your CMS and both see and manage the data as if it’s ordinary EPiServer pages. I’ve already begun to make a bunch of different page providers for pretty much anything (AD, Filesystem, Commerce Server, SQL Server, EPiServer Profiles, Community, …) – and there is definitely endless potential for its uses. However, until now I have had a small stone in my shoe whenever I was making a page provider. When inheriting from PageProviderBase, you have to manually map and handle guids, ids and urls. That’s a pain. Not only is it a lot of work, where it’s easy to introduce errors – but it can also be quite tricky to store the guids and ids for an external data source that doesn’t have those fields. Sure, if you’re making a XML provider like the sample one listed, it’s no problem to add a couple of extra attributes with a generated guid and id. But when you’re working with external data like the company product database, the user profiles stored in active directory, etc. it’s not particularly elegant to modify the external data in order to use it in your EPiServer.

So – I’ve started to make a new base class that handles that problem: The MappedPageProvider. The idea is that instead of working with id and guid you just have to map to one external string key. In order to do this it adds a table to the EPiServer database called tblPageProviderMappings, that it uses to keep track of all mappings. Once you start using the MappedPageProvider, it will add the table if it doesn’t exist.

Here’s an example of a simple hardcoded page provider implemented using the MappedPageProvider as a base:

public class TestProvider : MappedPageProvider
{
    protected override List<string> GetRootChildren()
    {
        return new List<string>() { "Allan", "Knudsen", "Kolle" };
    }
 
    protected override List<string> GetChildren(string Key)
    {
        if (Key == "Allan")
        {
            return new List<string>() { "Maximilian" };
        }
        return new List<string>();
    }
 
    protected override EPiServer.Core.PageData GetPage(string Key)
    {
        PageData pd = new PageData();
        base.InitializePageData(pd, Key, Key, (Key=="Maximilian") ? "Allan":null);
        pd.SetValue("MainBody", "Hardcoded body");
        SetPageStatus(pd, VersionStatus.Published);
        pd.SetValue("PageStartPublish", new DateTime(2009, 1, 1));
        return pd;
    }
 
    protected override string GetPageType(string Key)
    {
        return "[Public] Standard page";
    }
}

First, you need to list the string keys to the root children (the child pages of the providers entry point). In this example I’ve chosen to use real names instead of a more useful id – it just gives that cozy feel :-) I’ve also implemented the GetChildren method, where you get a key to a page and return a list of child-keys from that page. In this case there is only one child. We also need a method that can return a PageData for a given string key. A helper method for that is InitializePageData – which now has an overload that supports using keys. In this case I also choose to use the key as the page name. Finally, a method that can identify which PageType to use for a given key is also needed. All there is left is just to compile and register the provider in web.config.

mpp1

Here is the final result.

The “Test” node is in the local provider, and is set as the entryPoint.

 

 

 

 

Limitations

This Mapped Page Provider is just a first draft of a prototype. There is no support yet for saving, moving, deleting, searching and handling multiple versions / languages.

 

Download it here.

 Download full source here

UPDATE 27 APR 2009: Download updated with some bug-fixes, support for saving, and based on EPiServer CMS 5 R2 SP1.

20 January 2009


Comments

  1. Have used the mapped page providers. It sort of works, but you have to change a few thing to get it to work as intended. 1) In the CreateIfNotExist(MappedPPDB) you need to clode the connection before you attament to create the table. 2)LoadMapping(MappedPPDB) you need to lock the function so only one request access this method at the same time.
  2. Anders: I've used the Mapped Page Provider successfully in a number of prototypes already. However, I just noticed the the downloadable here was my original draft and not the current working version. It has now been updated. Now it's based on the DataAccessBase that has changed quite a bit in SP1. The LoadMapping method is also running synchronized.
  3. Strange.. the one use is also based on DataAccessBase. Could you please post a link to source code (MappedPPDB) that is latest?
  4. Now there is a source link. It's the same base class, but in SP1 a new approach to using it has been inroduced (using Action and Func). Try to reflect a bit in the data-layer changes between R2 and R2 SP1 - you'll be surprised :-)
  5. Nice code. Had to add locking around AddToCache else I got key already exists. guess this has something to do with the number of sub items I try to display
  6. Thanks for the tip. Updated the assemblies with that fix.
  7. Hi, Is there any intention to make the source code available for this e.g. on CodeResort ? Kind Regards, Chris
  8. Chris, Currently I'm pushing PM to get it into the product in version 6. But I suppose we could look into adding it to EPiCode. I'll get to it as soon as I have a moment.
  9. Hi Allan, I'm, having an issue with the page ID's that the mapped page provider creates. I have a page in my site which has ID 3. I attach my mapped page provider to this node. However, the page ID's that the mapped page provider creates appear to begin at 1, so page ID 3 is re-created under page 3 . . . Any ideas on what to do about this ? Cheers, Chris
  10. Hi again Allan, Further to my previous message, it appears that whenever I use page id 3 as the entry point for the page provider, page 3 gets duplicated within the page provider. I've tried this with a VERY simple page provider, and it always appears to be the case. Please contact me on chris.white@ioko.com to discuss the issue further. Kind Regards, Chris
  11. Hi Allan and Chris, did you ever find the reason for this entry page gets duplicated under itself? I having the exact same issue? And when I try the delete user group application crashes because of infinite loop caused probably by this duplicate entry page.
  12. An update to my problem: we fixed the duplicate id problem by changing the AddKey method in MappedPageProvider so that it adds 100000 to the IDs it creates. This is of course not the most elegant way because it could mean another collision in IDs when there is more than 100000 pages created to CMS but in our case this should not be the problem.
Post a comment    
User verification Image for user verification  
Allan Thræn

About me

I am a product manager @ EPiServer, with a passion for the more geeky side of things. My technical interests are typically focused around user problems, user experience,  search, information management, artificial intelligence and  personalization

On top of this blog I have the blog Allan On Technology and I often crosspost.

DISCLAIMER: Unless otherwise stated in the posts, this blog expresses my personal opinions, experiments and views, not necessarilly the views of EPiServer AB.

 834 page views this week.

 

 

Syndications


Archive


Tag cloud

EPiTrace logger