Работа с приложениями в Optimizely CMS 13

💡Примечание: Следующий контент был написан на основе Optimizely CMS 13 Preview 2 и может неточно отражать окончательную версию.

В рамках подготовки Stott Security и Stott Robots Handler для PaaS CMS 13 мне пришлось вернуться к ключевым функциям моих надстроек, использующих определения сайтов. Эти надстройки позволяют пользователю определять конфигурации robots.txt, llms.txt и security.txt в глобальном масштабе, для каждого сайта и для каждого хоста. В результате мне нужно иметь возможность считывать данные о различных конфигурациях сайта.

Доступ к определениям сайта/приложения

Поскольку CMS 13 взяла на себя инициативу SaaS и задумалась о более компонуемых архитектурах, произошел сдвиг от мышления о «сайтах» к размышлению о «приложениях». Также наблюдается переход к использованию двух разных конфигураций приложений. Существует традиционный «в процессе» Приложение CMS, которое представлено Веб-сайт класс, и есть «безголовый» приложение, которое представлено УдаленныйВеб-сайт сорт. Эти два приложения наследуют Приложение сорт.

Существующие ISiteDefinitionRepository сейчас устарел, но на данный момент работает и возвращает только в процессе приложения. Для доступа к обоим типам приложений вам необходимо использовать новый интерфейс Репозиторий приложений. Этот новый репозиторий предоставляет следующие методы для перечисления приложений:

// In-process applications
var data = await applicationRepository.ListAsync();

// Headless applications
var data = await applicationRepository.ListAsync();

// All applications
var data = await applicationRepository.ListAsync();
var data = await applicationRepository.ListAsync();

Еще одно ключевое изменение заключается в том, что поле GUID Id больше не существует. ISiteDefinitionRepository все еще работает, идентификатор заполняется пустым GUID в целях совместимости. Новые объекты используют имя Вместо этого оно генерируется как исправленная версия отображаемого имени в нижнем регистре при создании, а затем становится неизменяемым свойством.

Еще одно долгожданное изменение с Репозиторий приложений — это переход к асинхронным API, который упрощает написание неблокирующего и масштабируемого кода, особенно в сценариях с высокой пропускной способностью.

⚠️ Предупреждение о миграции: Если вы ранее вводили конфигурацию с помощью SiteDefinition.Id, вам понадобится стратегия миграции для сопоставления устаревших GUID с Application.Name. Не существует однозначной замены, и новое имя после создания становится неизменным.

Решение текущего приложения

Исторически сложилось так, что доступ к текущему веб-сайту для вашей текущей страницы будет осуществляться через SiteDefinition.Current. Это больше не доступно, и вместо этого нам нужно использовать IApplicationResolver вместо. Это обеспечивает доступ к следующим методам:

// Retrieve the application based on a host name 
var result = applicationResolver.GetByHostname(hostName, fallbackToDefault);
var result = await applicationResolver.GetByHostnameAsync(hostName, fallbackToDefault, cancellationToken);

// Retrieve the application based on a given content reference
var app = applicationResolver.GetByContent(contentReference, fallbackToDefault);
var app = await applicationResolver.GetByContentAsync(contentReference, fallbackToDefault, cancellationToken);

// Retrieve the application based on the current HTTP Context
var app = GetByContext();
var app = await GetByContextAsync(cancellationToken);

Декомпиляция DefaultApplicationResolver Я вижу, что GetByContext методы на самом деле просто оборачивают GetByContent и GetByHostName методы и попытайтесь сделать это сначала с помощью Content. Если ваша функциональность должна работать вне маршрута содержимого, то лучше получить приложение напрямую по имени хоста, просто имейте в виду, что это возвращает ApplicationHostResolution а не Приложение.

public async ValueTask GetByContextAsync(CancellationToken cancellationToken = default(CancellationToken))
{
    Application application = null;
    ContentReference routedContentLink = _routedContentLinkResolver.RoutedContentLink;
    if (!ContentReference.IsNullOrEmpty(routedContentLink))
    {
        application = await GetByContentAsync(routedContentLink, fallbackToDefault: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
    }

    if (application == null)
    {
        string hostName = _requestHostResolver.HostName;
        (application, _) = await GetByHostnameAsync(hostName, fallbackToDefault: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
    }

    return application;
}

Краткое содержание

CMS 13 заменяет традиционную концепцию сайтов приложениями, поддерживая как внутрипроцессные, так и автономные модели. Хотя устаревшие API-интерфейсы сайтов все еще существуют для обеспечения совместимости, новые разработки должны использовать IApplicationRepository и IApplicationResolver.

Read more:  Зеленский снова пытается ослабить власть Путина над Трампом

Переход от идентификаторов сайтов на основе GUID к неизменяемым именам приложений является наиболее значительным изменением и имеет реальные последствия для хранения и миграции конфигурации. Хотя это требует некоторой корректировки, новая модель приложения обеспечивает более чистую и гибкую основу для современных архитектур CMS.


Я OMVP, автор и сопровождающий Стотт Секьюрити и Стотт Роботс-обработчик для Optimizely CMS 12. Весь мой контент можно найти на сайте https://www.stott.pro/

30 января 2026 г.

По теме

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.