Base PageType fields

James Mosquito asked on February 25, 2021 18:38

Hi,

What would be the best way to retrieve a field value from the base pagetype when quering across multiple pagetypes using the DocumentHelper e.g.

var nodes = DocumentHelper
            .GetDocuments()
            .WhereTrue("FieldValueInBasePageType");

Currently I get an error: Invalid column name 'FieldValueInBasePageType'.

Is there a join I can do to retieve the relevant columns?

Thanks, James

Correct Answer

Dmitry Bastron answered on February 26, 2021 11:28

Hi James,

Laura is correct, you'd need to specify all page types in .Types() of your multi-document query, this will act as a sort of "join". You can get these classnames like this by the way:

private void Test()
{
    var documents = DocumentHelper.GetDocuments()
        .Types(GetClassnames())
        .WhereTrue("FieldValueInBasePageType");
}

private string[] GetClassnames()
{
    var baseClass = DataClassInfoProvider.GetDataClassInfo("custom.pageTypeClass");
    return DataClassInfoProvider.GetClasses()
        .WhereEquals("ClassInheritsFromClassID", baseClass.ClassID)
        .Select(x => x.ClassName)
        .ToArray();
}

Also, consider using caching in GetClassNames call as well as specifying .Columns() in your main query for better performance.

0 votesVote for this answer Unmark Correct answer

Recent Answers


Laura Frese answered on February 26, 2021 00:09

If this a custom field that exists on some pages and not all then you need to specify the page types that have this field. Also consider trying the TreeProvider

    // Creates a new tree provider instance
TreeProvider tree = new TreeProvider(MembershipContext.AuthenticatedUser);

// Retrieves the latest published version of all pages under a specified path that have a 'Document Name' starting with 'Apple'
MultiDocumentQuery products = tree.SelectNodes()
                        .Path("/Products/", PathTypeEnum.Children)
                        .WhereLike("DocumentName", "Apple%")
                        .ExcludePath("/Products/Sale", PathTypeEnum.Section)
                        .OnSite("CorporateSite")
                        .Culture("en-us");
0 votesVote for this answer Mark as a Correct answer

James Mosquito answered on February 26, 2021 10:54

Thanks Laura. The field value that I would like to target is in a base pagetype. E.g one that I set as the Inherits fields from page type value in the general properties of all other PageTypes.

0 votesVote for this answer Mark as a Correct answer

James Mosquito answered on February 26, 2021 15:14

Thanks Dimitry,

I got it working using the example you kindly provided.

James

0 votesVote for this answer Mark as a Correct answer

Elmar Höfinghoff answered on May 11, 2021 11:22 (last edited on May 11, 2021 11:45)

Here's what I did in K13R1.

  • Export the code of your page types and add the generated code files to your solution.
  • Add the following extension.

After this, you can access all base page fields without errors.

using CMS.DataEngine;
using CMS.DocumentEngine;
using System.Collections.Generic;
using System.Linq;

namespace Code.Extensions
{
    public static class MultiDocumentQueryExtensions
    {
        public static MultiDocumentQuery InheritsType(
            this MultiDocumentQuery query, string baseClassName)
        {
            // get base class
            DataClassInfo basePageClassInfo = DataClassInfoProvider
                .GetDataClassInfo(baseClassName);

            // get all inheritors of this base class
            List<DataClassInfo> basePageInheritors = DataClassInfoProvider
                .GetClasses()
                .WhereEquals(
                    nameof(DataClassInfo.ClassInheritsFromClassID), 
                    basePageClassInfo.ClassID)
                .ToList();

            // break if there are none
            if (!basePageInheritors.Any())
            {
                return query;
            }

            // return filtered query
            List<string> typeList = new List<string>();
            foreach(DataClassInfo type in basePageInheritors)
            {
                typeList.Add(type.ClassName);
            }
            return query.Types(typeList.ToArray());
        }
    }
}

Use it like this:

   using Code.Extensions;
   using CMS.DocumentEngine.Types.MySiteName;
   [...]
   MultiDocumentQuery query = DocumentHelper
      .GetDocuments()
      .InheritsType(BasePage.CLASS_NAME)
      .WhereFalse(nameof(BasePage.BasePageTeaserIsHidden));
0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.