Kentico MVC Pages data type, error while attempting to loop related pages

Stuart Freeman asked on January 27, 2020 19:53

Hi All, I have a Content-only Page type with a "Pages" data type field that links pages of different custom types from the parent document.

My intention is to loop through the Related documents as TreeNodes and grab link (NodeAliasPage) and link text (DocumentName) to create custom MenuItems.

I have tried every conceivable way to do this with the same result, exception thrown:

Object must implement IConvertible

I've tried this with and without the .Cast

    foreach (TreeNode page in footer.Fields.NavigationPages.Cast<TreeNode>())
    {
        // on second iteration the IConvertible error is thrown
        var menuItem = new MenuItemViewModel { MenuItemText = page.DocumentName, 
            MenuItemRelativeUrl = page.NodeAliasPath };
            vm.MenuItems.Add(menuItem);
    }

The issue seems to be that CMS.DocumentEngine attempts to cast the related item to the type of the first item in the collection on each iteration. And so on the start of the second iteration the error is always thrown. The first iteration works. Note: the first and second items have different Content-only Page types.

Is there a straight-forward solution for iterating through these docs in the "Pages" data type field? I am not doing anything custom in terms of querying this field. It comes populated with basic queries to the parent page.

Also tried these:

var noGo = footer.Fields.NavigationPages.Cast<TreeNode>().Select(x => new MenuItemViewModel
        {
            MenuItemText = ((TreeNode)x).DocumentName,
            MenuItemRelativeUrl = ((TreeNode)x).NodeAliasPath
        });

vm.MenuItems = footer.Fields.NavigationPages.OfType<TreeNode>().Select(page => new MenuItemViewModel
         {
             MenuItemText = "",
             MenuItemRelativeUrl = ""
         }).ToList(); 

Correct Answer

Dat Nguyen answered on January 27, 2020 22:54

Try getting related pages using MultiDocumentQuery.

In your case, the code would look like:

string relationshipDisplayName = "Footer (Navigation Pages)"; 
    //Relationship display name is the footer's class display name 
    //and the Pages field's field caption in parenthesis. 
    //See the CMS_RelationshipName database table.

var relationshipNameInfo = RelationshipNameInfoProvider.GetRelationshipNames()
    .WhereEquals("RelationshipDisplayName", relationshipDisplayName)
    .FirstOrDefault();

MultiDocumentQuery relatedPages = DocumentHelper.GetDocuments()
    .InRelationWith(footer.NodeGUID, relationshipNameInfo.RelationshipName);

Then you should be able to iterate through relatedPages without issue.

1 votesVote for this answer Unmark Correct answer

Recent Answers


Stuart Freeman answered on January 28, 2020 01:31

Hi @Dat

thanks for this. How can I order according to the order of the collection in the NavigationPages (Pages data type) field? If I can't order then what is the actual solution here? Don't use Pages as a collection to generate links for a given document? thanks!

0 votesVote for this answer Mark as a Correct answer

Dat Nguyen answered on January 28, 2020 02:32

I've never used this method but I believe this should do what you need. It returns MultiDocumentQuery. The first parameter is the relatedPages query from the sample code above.

RelationshipInfoProvider.ApplyRelationshipOrderData(
    relatedPages, 
    footer.NodeID, 
    relationshipNameInfo.RelationshipNameId);

Let me know if that works out. If not, the CMS_Relationship table does store relationship order, so I'll see if I can figure out the query using that data.

1 votesVote for this answer Mark as a Correct answer

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