2
votes

I just recently upgraded Umbraco from 4.7.2 to 7.1.9 and now in the process of slowly converting all legacy macroscripts to partial view macros. I have come across a few issues when using DescendantsOrSelf to iterate through nodes.

I have a macro that generates the side menu for my site (intranet). With version 4 the macro worked as expected on the whole site displaying the appropriate menu on the homepage and different side menu's on the child pages.

After the upgrade the below condition:

var model = GetParentSideMenu(CurrentPage);

@if (CurrentPage.AncestorsOrSelf("umbSomePageType").Where("Visible").First().HasValue("PageName") && CurrentPage.AncestorsOrSelf("umbSomePageType").Where("Visible").First().Id != model.Id)
{ ... }

@functions
{
public dynamic GetParentSideMenu(dynamic model)
{
    if (model.Level > 1)
    {
        do
        {
            if (model.umbSideMenuLinks.Count() > 0)
            {
                return model;
            }
            if (model.Level > 1) {
                model = model.Up();
            } else { break; }
        } while (model.Up() != null);

        return model;
    }
     else return model;
   }
}

Generates the following error when rendered on the homepage:

System.InvalidOperationException {"Sequence contains no elements"}

Inner Exception is null

The understanding here is that the page being rendered is not "umbSomePageType" so this condition should be false and move on but instead it throws the above exception.

The macro works fine when rendered on a "umbSomePageType" page but as the user is allowed to have further sub pages of a another type under "umbSomePageType" I have to manually check the "DocumentTypeAlias" and make sure the other if statements checking for that type of sub page are not executed because I get the same error as above.

Another issue I am facing is this doesn't return an iterable collection when it used to before in v4:

@if (model.DescendantsOrSelf("umbSideMenuLinks").Where("Visible").Count() > 0)
{
    foreach (var item in model.DescendantsOrSelf("umbSideMenuLinks").Where("Visible").First().Children)
{ ... } 
.... }

The if condition returns true but the foreach is unable to get any elements to iterate through.

Any help here will be greatly appreciated.

Thank You.

1
Any chance that you know where in the GetParentSideMenu the InvalidOperationException occurred at? For your second issue, I faced something similar and corrected it by checking if not null in addition to the call. - Jerode
Hey, sorry I should have specified that. The error was occurring in the if condition. Swapping out First() to FirstOrDefault() has solved that problem. - M Khan
Great, glad you worked it out. Maybe post the final solution and mark as resolved if possible. - Jerode
As for the second issue after debugging it for a little while I realized that in the older version when using "DescendantsOrSelf" would first check the Self and then the descendants. In v7 it checks the decedents first and it just so happens that the first descendant it finds has a "umbSideMenuLink" doc type but with no content inside and hence doesn't return anything. I am assuming this was something that was changed in the v7 ? Yeah I will do that tomorrow. - M Khan
thanks for that info, not aware of that change. I will have to take a look at a couple routines I have using "DescendantsOrSelf" to verify all is still well. - Jerode

1 Answers

0
votes

I was able to find a solution to the first problem I specified above. The error was occurring in the "if" condition due to the "CurrentPage" being a dynamic object, "FirstOrDefault()" needs to be used instead of "First()".

The second issue still stands and to further detail that issue if you have the following directory structure:

Root Folder/Homepage
- Second Level Folder
-- SideMenuLinks (umbSideMenuLinks)
-- SomePage...
- SideMenuLinks (umbSideMenuLinks)

In the above case if I am on the "HomePage" and I want to render the "SideMenuLinks" pertaining to the homepage and I use "DecedantOrSelf" it will go from the root folder to the second level folder and to the "SideMenuLinks" instead of first checking it "Self" which is the behaviour I desire. This is something that worked in Umbraco v4 but in v7 it drills into the sub directories first. Maybe if I reorder/sort the SideMenuLinks so they appear before the "Second Level Folder" ? Haven't tried that yet.

UPDATE: So I just tried the sorting and if I sort the tree this way:

Root Folder/Homepage
- SideMenuLinks (umbSideMenuLinks)
- Second Level Folder
-- SideMenuLinks (umbSideMenuLinks)
-- SomePage... 

It starts to work. In the future we will have to create the page structure this to make sure that the correct SideMenuLinks are hit.