Get property recursively

Vote:
 

Hi,

I have tried searching the forum, but without luck.

I am developing af EPiServer 7.5 site with MVC.

I have a BasePage type that all pages inherit from. Let's pretend this BasePage has a string property called Title, which means that every page in the pagetree now has a Title-field.

It's easy to get the Title property in my view, but what if I want to get the property recursively? So if the current page does not have a title filled out, I want it to look at the parents Title-property and so on, until it finds a page that has this value.

I have looked at this example, but it is over 4 years old, and I am not sure it is the best way to do it. http://joelabrahamsson.com/working-with-dynamic-properties-and-page-type-builder/

Thanks,

Rasmus

#80598
Jan 27, 2014 15:55
Vote:
 

You can use the ParentLink to get the parent.

http://world.episerver.com/Documentation/Class-library/?documentId=cms/7.5/b38e303b-a955-4dc6-4bd0-d954c4815ea2

Once you have the parent you can check if that has the property and if not, get its parent etc.

#80604
Jan 27, 2014 18:50
Vote:
 

Thanks, I was aware of this solution too, but I hoped there was a more "Built-in"-way to do it. I mean, it's a pretty common thing to do in most of the projects I am developing.

Well, I guess i have to make my own recursive function that runs all the way up to the top level until it finds a page where the property is filled out.

#80606
Jan 27, 2014 23:26
Vote:
 

The other way is using Dynamic properties, but I guess this is not what you want to do.

http://world.episerver.com/Documentation/Items/Developers-Guide/EPiServer-CMS/75/Content/Properties/Properties/

#80607
Edited, Jan 27, 2014 23:29
Vote:
 

Thanks,

I will look more into the concept of Dynamic properties, but I guess I will go for the custom function to retreive the property recursively.

#80608
Jan 27, 2014 23:34
Vote:
 

Hi Rasmus!

As Toni mentions, currently the built in solution for this is dynamic properties. However, we want to replace these with built in properties with inherritance support since dynamic properties use an old editing system and lack typed model support. Unfortunately, we have not had time to do this yet, so for now, I would probably add a helper method that resursively goes to the parents to find the closest defined value.

#80611
Jan 28, 2014 7:19
Vote:
 

Here's an example of an extension method for that:

    public static class ContentDataExtensions
    {

        public static T GetPropertyValueRecursive<T>(this ContentData contentData, string propertyName)
        {            
            var val = contentData.GetPropertyValue(propertyName, default (T));            
            if (val != null || PageEditing.PageIsInEditMode) 
                return val; 

            // get parent content data
            var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
            var parent = contentLoader.Get<ContentData>(((IContent) contentData).ParentLink);

            if (parent == null) // this must be the root page, return null or whatever
                return default(T);

            return parent.GetPropertyValueRecursive<T>(propertyName);
        }
    }
#117041
Feb 10, 2015 14:56
Vote:
 

Here's another way of doing this that I made. Maybe not effecient since it uses reflection, but it's typed and pretty cool;

public static TValue GetPropertyValueFromAncestor<TPageType, TValue>(this PageData page, Expression<Func<TPageType, TValue>> expression) where TPageType : PageData
{
    var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
    while (page.ParentLink != null && page.ParentLink != PageReference.EmptyReference)
    {
        var typedPage = page as TPageType;
        if (typedPage != null)
        {
            var expr = (MemberExpression)expression.Body;
            var prop = (PropertyInfo)expr.Member;
            var value = prop.GetValue(typedPage, null);

            if (value != null)
            {
                return (TValue)value;
            }
        }
        page = contentRepository.Get<PageData>(page.ParentLink);
    }
    return default(TValue);
}

Usage:

currentPage.GetPropertyValueFromAncestor<NewsListingPageBase, ContentReference>(i => i.NewsContainer);

Cheers
Fredrik

#133174
Aug 27, 2015 12:48
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.