Проблема с итерацией с использованием DescendantsOrSelf

Недавно я обновил Umbraco с 4.7.2 до 7.1.9 и сейчас медленно конвертирую все устаревшие макроскрипты в макросы частичного просмотра. Я столкнулся с несколькими проблемами при использовании DescendantsOrSelf для перебора узлов.

У меня есть макрос, который генерирует боковое меню для моего сайта (интранет). В версии 4 макрос работал должным образом на всем сайте, отображая соответствующее меню на главной странице и различные боковые меню на дочерних страницах.

После обновления следующее условие:

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;
   }
}

Генерирует следующую ошибку при отображении на главной странице:

System.InvalidOperationException {"Sequence contains no elements"}

Inner Exception is null

Понимание здесь заключается в том, что отображаемая страница не является «umbSomePageType», поэтому это условие должно быть ложным и двигаться дальше, но вместо этого выдает указанное выше исключение.

Макрос отлично работает при отображении на странице «umbSomePageType», но поскольку пользователю разрешено иметь дополнительные подстраницы другого типа в разделе «umbSomePageType», мне нужно вручную проверить «DocumentTypeAlias» и убедиться, что другие операторы if проверяют это тип подстраницы не выполняется, потому что я получаю ту же ошибку, что и выше.

Еще одна проблема, с которой я сталкиваюсь, заключается в том, что это не возвращает итерируемую коллекцию, когда она использовалась раньше в версии 4:

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

Условие if возвращает true, но foreach не может получить какие-либо элементы для итерации.

Любая помощь здесь будет принята с благодарностью.

Благодарю вас.


person M Khan    schedule 26.11.2014    source источник
comment
Есть ли шанс, что вы знаете, где в GetParentSideMenu произошло InvalidOperationException? Что касается вашей второй проблемы, я столкнулся с чем-то подобным и исправил его, проверив, не равен ли он нулю, в дополнение к вызову.   -  person Jerode    schedule 23.12.2014
comment
Эй, извините, я должен был указать это. Ошибка возникла в условии if. Замена First() на FirstOrDefault() решила эту проблему.   -  person M Khan    schedule 24.12.2014
comment
Отлично, рад, что у вас получилось. Возможно, опубликуйте окончательное решение и отметьте его как решенное, если это возможно.   -  person Jerode    schedule 24.12.2014
comment
Что касается второй проблемы, после ее отладки некоторое время я понял, что в более старой версии при использовании DescendantsOrSelf сначала проверялось Self, а затем потомки. В v7 он сначала проверяет потомков, и так уж получилось, что первый потомок, который он находит, имеет тип документа umbSideMenuLink, но без содержимого внутри и, следовательно, ничего не возвращает. Я предполагаю, что это было что-то, что было изменено в v7? Да, я сделаю это завтра.   -  person M Khan    schedule 24.12.2014
comment
спасибо за эту информацию, не знал об этом изменении. Мне нужно будет взглянуть на пару подпрограмм, которые я использую DescendantsOrSelf, чтобы убедиться, что все в порядке.   -  person Jerode    schedule 24.12.2014


Ответы (1)


Мне удалось найти решение первой проблемы, которую я указал выше. Ошибка возникала в условии «если» из-за того, что «CurrentPage» является динамическим объектом, вместо «First()» необходимо использовать «FirstOrDefault()».

Вторая проблема все еще остается в силе, и чтобы уточнить эту проблему, если у вас есть следующая структура каталогов:

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

В приведенном выше случае, если я нахожусь на «Домашней странице» и хочу отобразить «SideMenuLinks», относящиеся к домашней странице, и я использую «DecedantOrSelf», он перейдет из корневой папки в папку второго уровня и вместо этого в «SideMenuLinks». сначала проверить его «Я», что является желаемым поведением. Это то, что работало в Umbraco v4, но в v7 сначала выполняется переход к подкаталогам. Может быть, если я переупорядочу/отсортирую SideMenuLinks, чтобы они отображались перед «Папкой второго уровня»? Такого еще не пробовал.

ОБНОВЛЕНИЕ: Итак, я только что попробовал сортировку, и если я отсортирую дерево таким образом:

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

Он начинает работать. В будущем нам нужно будет создать структуру страницы, чтобы убедиться, что попадаются правильные ссылки SideMenuLink.

person M Khan    schedule 24.12.2014