Try our conversational search powered by Generative AI!

Anders Hattestad
Jan 28, 2011
  8702
(4 votes)

PageProviders and DDS, a match from heaven…

I’m working on a pet project where I’m trying to show community entities as a tree structure in EPiServer. image But then I tried to just show on structure bellow an other page using PageProviders.

To make a PageProvider you need both a unique number inside the page provider, and a guid that is unique across all elements. This is a perfect match with the DSS’s  Identity that both have a long and a guid inside.

So what I did was that I made myself a mapping table using the DDS Id as the id and guid for my page provider.

The properties in my DDS table is this:

image

 

 

 

 

and my episerver.config have these elements defined. Where should we get the page structure from, and where should they be displayed

Code Snippet
  1. <pageProvider>
  2.   <providers>
  3.       <add name="Club1" type="Itera.PageProviders.SubStructurPageProvider, EPiServer.Templates.RelatePlus"
  4.         entryPoint="43"
  5.           GetChildrenFrom="6"/>
  6.   </providers>
  7. </pageProvider>

The first method I need to implement is the one that returns page references for one page reference.

Code Snippet
  1. protected override PageReferenceCollection GetChildrenReferences(PageReference pageLink, string languageID)
  2. {
  3.     if (pageLink.CompareToIgnoreWorkID(base.EntryPoint))
  4.     {
  5.         var pages = EPiServer.DataFactory.Instance.GetChildren(GetChildrenFrom,
  6.             new LanguageSelector(languageID));
  7.         return SubStructurIDs.Ensure(pages, ProviderKey, pageLink.ToString());
  8.     }
  9.     else
  10.     {
  11.         var item = SubStructurIDs.GetItem(pageLink, ProviderKey);
  12.         if (item != null)
  13.         {
  14.             var pages = EPiServer.DataFactory.Instance.GetChildren(item.ContentPage,
  15.                 new LanguageSelector(languageID));
  16.             return SubStructurIDs.Ensure(pages, ProviderKey, pageLink.ToString());
  17.         }
  18.     }
  19.     return new PageReferenceCollection();
  20. }

I call the Ensure method and that stores the page references using the DDS. And the use the Id in the DDS table to make the “new” page link.

Code Snippet
  1. public static PageReferenceCollection Ensure(PageDataCollection pages, string providerKey,string parentPageLink)
  2. {
  3.     PageReferenceCollection result = new PageReferenceCollection();
  4.  
  5.     var query = from item in Store.Items<SubStructurIDs>() where
  6.                     item.ProviderKey == providerKey &&
  7.                     item.ParentPageLink == parentPageLink
  8.                 select item;
  9.     var hash = new Dictionary<int, SubStructurIDs>();
  10.     foreach (var item in query)
  11.     {
  12.         hash.Add(item.ContentPage.ID, item);
  13.     }
  14.     foreach (var page in pages)
  15.     {
  16.         
  17.         if (hash.ContainsKey(page.PageLink.ID))
  18.         {
  19.             result.Add(hash[page.PageLink.ID].ThisPageLink);
  20.             hash.Remove(page.PageLink.ID);
  21.         }
  22.         else
  23.         {
  24.             var newItem = new SubStructurIDs();
  25.             newItem.ContentPage = page.PageLink;
  26.          
  27.             newItem.ParentPageLink = parentPageLink;
  28.             newItem.ProviderKey = providerKey;
  29.             Store.Save(newItem);
  30.             result.Add(newItem.ThisPageLink);
  31.  
  32.         }
  33.     }
  34.     if (hash.Count > 0)
  35.     {
  36.         //Need to delete, or in other lang
  37.     }
  38.     return result;
  39. }

 

The I need to implement 2 functions, one where we have the page link and the find the guid, and one that have the guid and needs to find the page Link. These to are pretty much alike, and one looks like this

Code Snippet
  1. protected override Uri ResolveLocalPage(Guid pageGuid, out PageReference pageLink)
  2. {
  3.     var item = SubStructurIDs.GetItem(pageGuid, ProviderKey);
  4.      if (item != null)
  5.      {
  6.          pageLink = item.ThisPageLink;
  7.          return CreateUri(pageLink, item);
  8.      }
  9.      pageLink = PageReference.EmptyReference;
  10.      return null;
  11. }

Then we need to return a page

Code Snippet
  1. protected override PageData GetLocalPage(PageReference pageLink, ILanguageSelector languageSelector)
  2. {
  3.      var item = SubStructurIDs.GetItem(pageLink, ProviderKey);
  4.      if (item != null)
  5.      {
  6.          PageData org = EPiServer.DataFactory.Instance.GetPage(item.ContentPage, languageSelector);
  7.          if (org != null)
  8.          {
  9.              org = org.CreateWritableClone();
  10.              org.PageLink = pageLink;
  11.              org.ParentLink = PageReference.Parse(item.ParentPageLink);
  12.              org.PageGuid = item.Id.ExternalId;
  13.              return org;
  14.          }
  15.      }
  16.      return null;
  17. }

And then we are good to go.

Full code here

Jan 28, 2011

Comments

Mattias Minerbi
Mattias Minerbi Jan 16, 2013 12:20 PM

First of all, thanks for sharing this code!
I wonder..... lets say you have "segment A" that you want to copy (get all children from) and put it in different places in your epi-tree (multiple entry points, in my case a lot of places) is it possible to set entry points programmaticly in some way?
Will this solution work well with cached elements etc i.e lets say I update a page from my 'segment A' will that page will be updated for all places (every entry points).
It would be nice if a user could create a page in the epi-tree which has a page property that points out where to fetch data from and render that page and all children from current place in the epi-tree structure.... is that possible with this solution

Thanks in advance!

Anders Hattestad
Anders Hattestad Jan 16, 2013 05:47 PM

Hi, to add this code is needed:

var provider = new SubStructurPageProvider();
var config = new NameValueCollection();
config.Add("entryPoint", EPiPageStart.ToString());
config.Add("name", ProviderKey);
config.Add("GetChildrenFrom", "244");
provider.Initialize(ProviderKey, config);
DataFactory.Instance.ProviderMap.AddPageProvider(provider);

To remove this code:
DataFactory.Instance.ProviderMap.RemovePageProvider(ProviderKey);

Have made myself a edit plugin that enables me to mount pages bellow me
mail me at anders@hattestad.net if you want the code

Please login to comment.
Latest blogs
Visitor Groups Usage Report For Optimizely CMS 12

This add-on offers detailed information on how visitor groups are used and how effective they are within Optimizely CMS. Editors can monitor and...

Adnan Zameer | Apr 18, 2024 | Syndicated blog

Azure AI Language – Abstractive Summarisation in Optimizely CMS

In this article, I show how the abstraction summarisation feature provided by the Azure AI Language platform, can be used within Optimizely CMS to...

Anil Patel | Apr 18, 2024 | Syndicated blog

Fix your Search & Navigation (Find) indexing job, please

Once upon a time, a colleague asked me to look into a customer database with weird spikes in database log usage. (You might start to wonder why I a...

Quan Mai | Apr 17, 2024 | Syndicated blog

The A/A Test: What You Need to Know

Sure, we all know what an A/B test can do. But what is an A/A test? How is it different? With an A/B test, we know that we can take a webpage (our...

Lindsey Rogers | Apr 15, 2024