How to access multiple page types in K#?

Ondřej Takács asked on May 26, 2020 15:01

I need to write repeater that works with two different page types. I am listing page type "Person" and I need to access field from "Project" page type in where condition.

How do I do that?

I would like something like accessing custom tables:

CMSContext.Current.GlobalObjects.CustomTables["Project"].Items.Any("PersonId = " + Id)

But there is no global object for page types. There is only DocumentType but I didn't find actual data items there, only general properties:

CMSContext.Current.GlobalObjects.DocumentTypes["Project"]

I also tried listing documents, but filtering by className returns null:

CMSContext.Current.Documents.Where(ClassName = "Project")

Any ideas?

Correct Answer

Zdeněk Cetkovský answered on June 5, 2020 18:02

Hello Ondřej,

I'm posting additional info based on our discussion in other channel, so that others can see the possible solution to this aim too.

There is a possibility to filter the obtained collection using Filter method, which offers kind of a workaround for the limitation of single Where condition:

Documents.WithAllData.Where("ClassName = 'NAP.Projekt'").Filter(Osoba1 == Id)

Please note the difference in syntax of Where condition (string) and Filter condition (direct macro boolean expression).

Nevertheless, there is a more direct way to get the data and that is to specify corresponding ClassNames for the TreeNodeCollection that you get from the "Documents" entity. With such approach, you will have the required columns available in the primary Where condition:

Documents.ClassNames("NAP.Projekt").WithAllData.Where("Osoba1 = " + Id)

One recommendation here - in case of frequent calls of such macro, it may be a good idea to restrict the columns you need to the minimum, by adding the Columns modifier method:

Documents.ClassNames("NAP.Projekt").WithAllData.Columns("DocumentName, Osoba1").Where("Osoba1 = " + Id)

This is an "extreme" version of columns subset, you can check the available columns e.g. in System app -> Macros -> Console and choose those you need in the place of your macro.

Cheers,
Zdeněk

0 votesVote for this answer Unmark Correct answer

Recent Answers


Brenden Kehren answered on May 26, 2020 15:19

Something like

Documents["/Path"].Where("ClassName = 'your.class'")

Should get you close. I'd test these macros out in the System > Macros app

0 votesVote for this answer Mark as a Correct answer

Ondřej Takács answered on May 26, 2020 15:34

Thank you for your answer. That got me a list of documents of given class. Now I just need to filter them by page type properties, but they are not accessible in where condition. I would like something like:

Documents["/Path"].Where("ClassName = 'your.class'").Where("MyProperty = 'value'")

Is there any way to do it?

0 votesVote for this answer Mark as a Correct answer

Peter Mogilnitski answered on May 26, 2020 16:00

There is no double WHERE.

Documents["/Path"].Where("ClassName = 'your.class'").FirstItem.MyProperty

if Myproperty is class specific you need to use .WithAllData. But to me it looks like you will be better off with a custom macro where you can use your document query API at full extent. Macro is a bit limited here.

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on May 26, 2020 16:01 (last edited on May 26, 2020 16:05)

This works for me.

Documents["/path"].AllChildren.WithAllData.Where("ClassName = 'CMS.MenuItem' OR ClassName = 'CMS.File'")

0 votesVote for this answer Mark as a Correct answer

Ondřej Takács answered on May 27, 2020 12:40

Thank you for your suggestions. I know see how to access custom page type properties of individual document.

I still need to find a way how to get list of specific page types with given property value using macro expression.

For example, I have custom page type Project with custom field price. I want to write a macro expression that will return all projects with price greater than 100. How do I do that?

I would like to avoid writing custom macro for this, I have never done it and it seems complicated. Or maybe someone else has written custom macro that can do it? I think that many people would find this useful.

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on May 27, 2020 12:51

You need to build the where statement like I did in my previous answer. Continue to add AND or OR conditions to complete your statement.

0 votesVote for this answer Mark as a Correct answer

Ondřej Takács answered on May 27, 2020 13:21

I tried it and it is not working. It throws me SQL error, that the column is unknown.

I can access the property of single page, this is working, where Osoba1 is my custom field property:

Documents.WithAllData.Where("ClassName = 'NAP.Projekt'")[0].Osoba1

This is not working:

Documents.WithAllData.Where("ClassName = 'NAP.Projekt' AND Osoba1 = '1'")

It throws error with this SQL Query:

SELECT DISTINCT [ClassName]
FROM
  (SELECT [ClassName],
          ROW_NUMBER() OVER (PARTITION BY NodeID
                             ORDER BY CASE
                                          WHEN [DocumentCulture] = @DocumentCulture THEN 1
                                          ELSE 2
                                      END,
                                      DocumentCulture) AS [CMS_C]
   FROM View_CMS_Tree_Joined AS V WITH (NOLOCK,
                                        NOEXPAND)
   LEFT OUTER JOIN COM_SKU AS S WITH (NOLOCK) ON [V].[NodeSKUID] = [S].[SKUID]
   WHERE (ClassName = 'NAP.Projekt'
          AND Osoba1 = '1')
     AND [NodeSiteID] = @NodeSiteID ) AS SubData
WHERE [CMS_C] = @CMS_C
ORDER BY ClassName

And it makes sense. Join of table "NAP_Projekt" is missing.

Any way how to fix this?

0 votesVote for this answer Mark as a Correct answer

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