Проблема с программным обновлением настроек текущей навигации в Sharepoint

В этой статье я хочу рассказать об одной проблеме, с которой мы столкнулись при изменении настроек навигации. В интранете было создано много сайтов публикаций (publishing sites). Нужно было обновить настройки текущий навигации (current navigation) на всех сайтах, используя установку “Отображать элементы с родительского сайта” (русского языкового пакета нет, поэтому перевод может быть неточным. Оригинал: Display the same navigation items as the parent site):

Я создал небольшую утилиту, которая обновляет настройки навигации на всех сайтах:

class Program
{
    static void Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.WriteLine("Usage: UpdateNavigation.exe <site_url>");
            return;
        }

        Console.WriteLine("Start");
        using (var site = new SPSite(args[0]))
        {
            using (var web = site.OpenWeb())
            {
                foreach (SPWeb subweb in web.Webs)
                {
                    walk(subweb);
                }
            }
        }
        Console.WriteLine("Finish");
    }

    private static void walk(SPWeb web)
    {
        if (web == null)
        {
            return;
        }
        
        Console.WriteLine("Check web '{0}'", web.Url);
        var pweb = PublishingWeb.GetPublishingWeb(web);
        if (!pweb.Navigation.InheritCurrent)
        {
            Console.WriteLine("\tInherit current navigation for '{0}'", web.Url);
            pweb.Navigation.InheritCurrent = true;
            pweb.Web.Update();
        }

        foreach (SPWeb subweb in web.Webs)
        {
            walk(subweb);
        }
    }
}

Как видно из примера, она очень простая: перебираем все сайты рекурсивно и изменяем текущую навигацию. При этом она проверяет, установлено ли свойство PublishingWeb.Navigation.InheritCurrent в true, и устанавливает его только в случае, если свойство установлено в false (чтобы минимизировать обновления и обращения к контент базе на production-е). Утилита успешно отработала и обновила настройки всех сайтов сайт-коллекции, чтобы наследовать навигацию от родительского (рутового) сайта. Однако после этого на некоторых сайтах (не на всех) на странице Настройки сайта >Навигация для текущей навигации была выбрана опция “Отображать текущий сайт, элементы под текущим сайтом, и соседей” (Display the current site, the navigation items below the current site, and the current site’s siblings):

При этом, что было еще более странным, в UI навигация отображалась правильно на всех сайтах, т.е. на всех них использовалась навигация родительского сайта. Более того, когда я второй раз запустил утилиту, она не обновила ни одного сайта, что означало что PublishingWeb.Navigation.InheritCurrent установлено в true.

После этого я начал изучать логику класса страницы AreaNavigationSettings.aspx (именно она открывается когда вы выбираете Настройки сайта >Навигация): Microsoft.SharePoint.Publishing.Internal.CodeBehind.AreaNavigationSettingsPage. В нем имеются следующие элементы управления типа HtmlInputRadioButton для каждой опции настроек текущей навигации:

Идентификатор Название
inheritLeftNavRadioButton Отображать элементы с родительского сайта
showSiblingsLeftNavRadioButton Отображать текущий сайт, элементы под текущим сайтом, и соседей
uniqueLeftNavRadioButton Отображать только элементы под текущим сайтом

Вот как эти контролы используются:

protected override void OnLoad(EventArgs e)
{
    ...
    this.inheritLeftNavRadioButton.Checked =
        base.CurrentPublishingWeb.Navigation.InheritCurrent;
    this.showSiblingsLeftNavRadioButton.Checked =
        base.CurrentPublishingWeb.Navigation.ShowSiblings;
    this.uniqueLeftNavRadioButton.Checked =
        !base.CurrentPublishingWeb.Navigation.InheritCurrent && !this.showSiblingsLeftNavRadioButton.Checked;
    ...
}

protected void OKButton_Click(object sender, EventArgs e)
{
    ...
    publishingWeb.Navigation.InheritCurrent =
        this.inheritLeftNavRadioButton.Checked;
    publishingWeb.Navigation.ShowSiblings =
        this.showSiblingsLeftNavRadioButton.Checked;
    ...
    publishingWeb.Web.Update();
    base.RedirectToFinishUrl();
}

Как видно, несмотря на то, что все 3 элемента управления относится к одной группе (это означает, что через UI можно установить только один из них), программно можно установить оба свойства PublishingWeb.Navigation.InheritCurrent и PublishingWeb.Navigation.ShowSiblings в true. Через UI так сделать нельзя. При этом, как видно из кода, когда оба свойства установлены в true, Sharepoint выделит настройку “Отображать текущий сайт, элементы под текущим сайтом, и соседей”, потому что контрол showSiblingsLeftNavRadioButton, который соответствует данной опции, инициализируется в коде после контрола inheritLeftNavRadioButton, соответствующего опции “Отображать элементы с родительского сайта”. Такая реализация, на мой взгляд, способствует появлению ошибок, потому что если пользователь нажмет Ok на странице с настройками, то, ничего явно не меняя на странице, он изменит PublishingWeb.Navigation.InheritCurrent с true на false, при этом PublishingWeb.Navigation.ShowSiblings останется true.

Для того, чтобы исправить эту проблему, я добавил одну строку кода в утилиту. После того, как она отработала, все сайты показывали правильное значение “Отображать элементы с родительского сайта”:

var pweb = PublishingWeb.GetPublishingWeb(web);
pweb.Navigation.InheritCurrent = true;
pweb.Navigation.ShowSiblings = false;
pweb.Web.Update();

Имейте ввиду эту особенность, когда будете обновлять настройки навигации через объектную модель.

Реклама

Об авторе sadomovalex

Старший инженер, team lead, консультант. Работаю в стеке .Net. Последние несколько лет занимаюсь разработкой enterprise приложений под Sharepoint, чему и будет в основном посвящена тематика этого блога. Также активно использую и интересуюсь ASP.Net MVC, DDD, TDD, Agile. Активно участвую в жизни многих профессиональных сообществ, SPb .Net UG, SPb ALT.Net, rsdn, Finland SP UG и др.
Запись опубликована в рубрике Navigation, Sharepoint, UI. Добавьте в закладки постоянную ссылку.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s