A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More


Jan 16, 2011
  5205
(0 votes)

Chain of data fetching

I’m sure you are familiar with the EPiServer feature that allows a page to fetch data from another page. A webeditor can easily enable this feature in edit mode, and this works fine.

But what about a page that fetches data from a page that fetches data from another page? In this case we have a chain of 3 pages in inheritance. What does EPiServer do about this?

Let’s try:

  • Page A
    • Heading – “Base Page”
    • MainBody – “Base Page Body”
  • Page B
    • Heading – “Company Page”
    • MainBody – empty
    • Fetches data from Page A
  • Page C
    • Heading – “Department Page”
    • MainBody – empty
    • Fetches data from Page B

When showing Page B the MainBody propertys value will be “Base Page Body”. However, when showing Page C the MainBody property will be empty.

Let’s say you want to set up a site for a big company with subcompnaies and departments. 3 chains. And the top company want to distribute pages to the subcompanies with company guidelines that can be overridden. And, likewise, the subcompanies want to distribute those pages to the departments.

One way of getting this to work is to have chains of data-fetching. In our example, this means that Page C’s MainBody would not be empty when shown. It would have shown data from Page A.

The solution to this is to implement your own GetPropertyHandler. Using reflector, I fetched the code for EPiServer’s default property handler, and modified it:

 

namespace EPiServer.Custom.Handlers
{
    public class PropertyHandlers
    {
        public static PropertyData DefaultPropertyHandler(string name, PropertyDataCollection properties)
        {
            PropertyData data = properties.Get(name);
            if (data != null)
            {
                if (!data.IsNull || data.IsMetaData)
                {
                    return data;
                }

            }
            PropertyData data3 = FetchDataFrom(name, properties);
            if ((data3 != null) && (data3.Value != null))
            {
                return data3;
            }
            return (DynamicPropertyCache.DynamicPropertyFinder.FindDynamicProperty(name, properties) ?? data);
        }

        public static PropertyData FetchDataFrom(string name, PropertyDataCollection properties)
        {
            PropertyData data = properties.Get("PageShortcutType");
            if (((data == null) || (data.Value == null)) || (((PageShortcutType)data.Value) != PageShortcutType.FetchData))
            {
                return null;
            }
            data = properties.Get("PageShortcutLink");
            if (data == null)
            {
                return null;
            }
            PageReference pageLink = (PageReference)data.Value;
            if (!PageReference.IsValue(pageLink))
            {
                return null;
            }
            string languageBranch = properties.Get("PageLanguageBranch").Value as string;
            return GetPropertyFromPage(pageLink, languageBranch, name);
        }

        private static PropertyData GetPropertyFromPage(PageReference fetchPageLink, string languageBranch, string propertyName)
        {
            PageData page;
            if (string.IsNullOrEmpty(languageBranch))
            {
                page = DataFactory.Instance.GetPage(fetchPageLink);
            }
            else
            {
                page = DataFactory.Instance.GetPage(fetchPageLink, LanguageSelector.Fallback(languageBranch, true));
            }
            PropertyData data2 = page.Property.Get(propertyName);
            if (((data2 != null) && !data2.IsLanguageSpecific) && (data2.Value == null))
            {
                return DataFactory.Instance.GetPage(page.PageLink, LanguageSelector.MasterLanguage()).Property.Get(data2.Name);
            }
            if (string.Compare(propertyName, "MainBody", StringComparison.OrdinalIgnoreCase) == 0)
            {
                var data3 = FetchDataFrom(propertyName, page.Property);
                if (data3 != null)
                {
                    return data3;
                }
            }
            return data2;
        }
     

    }
}

As you can see from the code, this fetch data logic is recursive as long as the property is named “MainBody”.

And then, you have hook up this handler in Global.asax Application_Start method:

        protected void Application_Start(Object sender, EventArgs e)
        {
            XFormControl.ControlSetup += new EventHandler(XForm_ControlSetup);
            PropertyDataCollection.GetHandler = EPiServer.Custom.Handlers.PropertyHandlers.DefaultPropertyHandler;
        }

I guess there are other ways of solving chains of inheritance, feedback is very welcome Smilefjes

Jan 16, 2011

Comments

bvskanth@gmail.com
bvskanth@gmail.com Jan 17, 2011 04:44 PM

Nice post :)

Please login to comment.
Latest blogs
Building simple Opal tools for product search and content creation

Optimizely Opal tools make it easy for AI agents to call your APIs – in this post we’ll build a small ASP.NET host that exposes two of them: one fo...

Pär Wissmark | Dec 13, 2025 |

CMS Audiences - check all usage

Sometimes you want to check if an Audience from your CMS (former Visitor Group) has been used by which page(and which version of that page) Then yo...

Tuan Anh Hoang | Dec 12, 2025

Data Imports in Optimizely: Part 2 - Query data efficiently

One of the more time consuming parts of an import is looking up data to update. Naively, it is possible to use the PageCriteriaQueryService to quer...

Matt FitzGerald-Chamberlain | Dec 11, 2025 |

Beginner's Guide for Optimizely Backend Developers

Developing with Optimizely (formerly Episerver) requires more than just technical know‑how. It’s about respecting the editor’s perspective, ensurin...

MilosR | Dec 10, 2025

Optimizely PaaS Administrator Certification : Free for Everyone

Optimizely has recently launched a free PaaS Administrator Certification. https://academy.optimizely.com/student/activity/2958208-paas-cms-administ...

Madhu | Dec 9, 2025 |

Fixing TinyMCE Initialization Failures in Optimizely CMS: A Hidden Pipeline Issue with .NET SDK Versions

Over the past few weeks, several Optimizely CMS projects began experiencing a puzzling failure: XHtmlString fields stopped initializing TinyMCE in...

Francisco Quintanilla | Dec 9, 2025 |