PageCharm

Разработчикам

Razor API

Руководство разработчика PageCharm

Справочник по объектам и методам, которые обычно используются во вьюшках: PageCharmPageModel, IPageCharmContentQuery, медиа, настройки, slug и URL helpers.

Что подключать во вьюшке

Публичное представление получает модель PageCharmPageModel. Дополнительные сервисы можно внедрять обычным Razor @inject: чаще всего это IPageCharmContentQuery для контента и IPageCharmSettings для настроек сайта.

Сервис Для чего Пример
PageCharmPageModel Текущая страница, блок, шаблон, view и словарь атрибутов. @model PageCharmPageModel
IPageCharmContentQuery Публичные запросы к контенту CMS: меню, списки, карточки, хлебные крошки, поиск. @inject IPageCharmContentQuery Content
IPageCharmSettings Чтение настроек из раздела «Настройки». @inject IPageCharmSettings Settings
IPageCharmDictionaryQuery Чтение словарей и их значений для фильтров, навигации и форм на публичном сайте. @inject IPageCharmDictionaryQuery Dictionaries
IPageCharmUrlNormalizer Нормализация публичного пути: слеши, пустой путь, регистр. @inject IPageCharmUrlNormalizer Urls
IPageCharmSlugGenerator Создание slug из строки, включая русскую транслитерацию. @inject IPageCharmSlugGenerator Slugs

PageCharmPageModel

Свойство Тип Что содержит
Content CmsContent Текущий контент: Id, Name, Url, ParentId, Order, Active, IsHome, атрибуты и медиа.
Block CmsBlock Блок текущего контента. Удобно для заголовков и контекстной логики.
Template CmsTemplate Шаблон текущего контента. Если у шаблона нет View, публичная страница не рендерится.
View CmsView? Представление, через которое рендерится контент.
Attributes IReadOnlyDictionary<string, CmsContentAttribute> Атрибуты текущего контента по alias. Обычно удобнее использовать Content.Get<T>("alias").

Чтение полей контента

Метод Параметры Возвращает Когда использовать
content.Get<T>(alias) alias — alias поля шаблона. T?. Если поля нет или значение пустое, вернется default. Основной способ читать заголовки, цены, даты, JSON и простые значения.
content.TryGet<T>(alias, out value) alias и out T? value. true, если значение есть и сконвертировано; иначе false. Когда нужно отличить отсутствующее поле от значения по умолчанию.

Поддерживаемые типы для Get<T>: string, int, long, decimal, bool, DateOnly, TimeOnly, DateTimeOffset. Для сложных типов PageCharm пытается десериализовать JsonValue через System.Text.Json.

Медиа helpers

Метод Параметры Возвращает Пример
content.GetMedia() Нет. IReadOnlyList<CmsMediaAsset> медиа, привязанных к контенту без конкретного поля. var attachments = Model.Content.GetMedia();
content.GetMedia(alias) alias поля типа Image, Images, File или Files. Все медиа конкретного поля. var gallery = item.GetMedia("gallery");
content.GetFirstMedia(alias) alias медиа-поля. CmsMediaAsset? — первый файл поля или null. var cover = item.GetFirstMedia("cover");
content.GetImages(alias) alias медиа-поля. Только файлы с ContentType, который начинается с image/. foreach (var image in item.GetImages("gallery"))
content.GetFiles(alias) alias медиа-поля. Все не-картинки из поля. foreach (var file in item.GetFiles("docs"))
content.GetVideo(alias) alias поля типа Video или Videos. CmsVideo? — первый ролик поля или null. var trailer = item.GetVideo("trailer");
content.GetVideos(alias) alias поля типа Video или Videos. IReadOnlyList<CmsVideo>. foreach (var video in item.GetVideos("reviews"))
content.GetTags(alias) alias поля типа Tags. IReadOnlyList<CmsTag>. foreach (var tag in item.GetTags("topics"))
media.GetPresetUrl(alias) alias пресета изображения. Публичный путь resized-варианта вида /_pagecharm/images/{id}/{preset}/{file}. <img src="@cover.GetPresetUrl("card")">
video.GetPreviewUrl() Нет. URL картинки предпросмотра, если ее удалось получить или вывести из ссылки. <img src="@video.GetPreviewUrl()">
video.GetEmbedUrl() Нет. Embed URL для iframe, если он есть у провайдера. <iframe src="@video.GetEmbedUrl()"></iframe>

CmsMediaAsset содержит Id, FileName, ContentType, Size, StorageKey, Url, Alt, FocalX, FocalY, MetadataJson, CreatedAt. Для локального storage Url обычно относительный, например /uploads/image.jpg; для CDN/S3 может быть абсолютным. Для resized-варианта используйте image.GetPresetUrl("card"); он вернет путь вида /_pagecharm/images/{id}/{preset}/{file}.

IPageCharmContentQuery: фильтры

Все методы фильтрации возвращают новый IPageCharmContentQuery. Это позволяет переиспользовать базовый запрос для CountAsync() и списка. Если сортировку не указать, PageCharm сортирует по ручному порядку Order, затем по Id.

Метод Параметры Что делает
Active(active = true) bool active. По умолчанию true. Выбирает активный контент, учитывая системное расписание в версиях, где оно поддерживается. Active(false) выбирает неактивный контент. Без этого метода возвращаются оба состояния.
FromBlocks(params blockAliases) Один или несколько alias блоков. Фильтрует контент по блокам. Пустой список недопустим.
WithTemplates(params templateAliases) Один или несколько alias шаблонов. Фильтрует по шаблонам. Удобно для списков карточек разных типов.
ChildrenOf(parentId) long parentId. Возвращает дочерний контент конкретного родителя.
Search(text) Непустой текст. Ищет по всем текстовым и JSON-значениям атрибутов. Не ищет по системным Name и Url.
SearchFields(text, params fieldAliases) Текст и список alias полей. Ищет только в перечисленных текстовых/JSON-полях.
WhereFieldContains(fieldAlias, value) Alias поля и непустая строка. LIKE contains по StringValue и JsonValue. % и _ экранируются.
WhereFieldEquals(fieldAlias, value) string?, int, long, decimal, bool, DateOnly, TimeOnly, DateTimeOffset. Точное сравнение с соответствующим типизированным столбцом атрибута. Для строк проверяются StringValue и JsonValue.
WhereIntegerFieldBetween(fieldAlias, min, max) long? min, long? max. Диапазон по целому числу. Любую границу можно оставить null.
WhereDecimalFieldBetween(fieldAlias, min, max) decimal? min, decimal? max. Диапазон по decimal-полю.
WhereDateFieldBetween(fieldAlias, start, finish) DateOnly? start, DateOnly? finish. Диапазон по дате без времени.
WhereDateTimeFieldBetween(fieldAlias, start, finish) DateTimeOffset? start, DateTimeOffset? finish. Диапазон по дате и времени.
WithAnyTags(params tagAliases) Один или несколько alias тегов. Оставляет контент, у которого есть хотя бы один из тегов в любом поле Tags.
WithAllTags(params tagAliases) Один или несколько alias тегов. Оставляет контент, у которого есть все перечисленные теги в любых полях Tags.
WhereTagsContain(fieldAlias, params tagAliases) Alias поля Tags и один или несколько alias тегов. Оставляет контент, у которого конкретное поле содержит все перечисленные теги.

IPageCharmContentQuery: сортировка и завершение

Метод Параметры Возвращает Что важно
OrderByField(fieldAlias, sortType, descending) Alias поля, CmsContentFieldSortType, флаг направления. Новый query. Контент без значения поля идет после контента со значением; вторичная сортировка — Id.
OrderByFieldOrCreatedAt(fieldAlias, sortType, descending) Alias поля, CalendarDate или Instant, флаг направления. Новый query. Сортирует по полю даты, используя CreatedAt для записей без значения.
OrderByPublishAt(descending) Флаг направления. Новый query. Сортирует по системной дате публикации, используя CreatedAt как запасное значение, и выполняет paging в базе.
Skip(count) int count, не меньше 0. Новый query. Пропускает элементы для paging.
Take(count) int count, не меньше 0. Новый query. Ограничивает размер страницы.
FindByIdAsync(id) long id, optional CancellationToken. Task<CmsContent?>. Учитывает уже заданные фильтры query, например Active().
FindByUrlAsync(url) URL или путь, optional token. Task<CmsContent?>. URL нормализуется через IPageCharmUrlNormalizer.
GetBreadcrumbsAsync(content, includeCurrent) Контент, флаг включения текущей страницы, optional token. Task<IReadOnlyList<CmsContent>>. Идет вверх по ParentId, защищен от циклов, учитывает Active().
FirstOrDefaultAsync() Optional token. Task<CmsContent?>. Возвращает первый элемент после фильтров и сортировки.
CountAsync() Optional token. Task<long>. Считает количество без загрузки полной модели контента.
ToListAsync() Optional token. Task<IReadOnlyList<CmsContent>>. Загружает блок, шаблон, view, атрибуты, медиа контента и медиа атрибутов.

Типы сортировки

Тип Столбец значения Для каких полей
Text StringValue или JsonValue String, Text, Html, Markdown, Select, Json.
WholeNumber IntegerValue Integer.
DecimalNumber DecimalValue Decimal.
Flag BooleanValue Boolean.
CalendarDate DateValue Date.
ClockTime TimeValue Time.
Instant DateTimeValue DateTime.

Словари

IPageCharmDictionaryQuery читает раздел «Словари» без прямой зависимости view от EF Core. Tags используют словари как множество значений и фильтруются через WithAnyTags, WithAllTags, WhereTagsContain. Select со словарным источником хранит один alias значения, поэтому фильтруется как обычное поле: WhereFieldEquals("brand", "avtovaz").

Метод Параметры Возвращает Пример
Dictionaries.GetDictionariesAsync() Optional token. Task<IReadOnlyList<CmsTagDictionary>>. var dictionaries = await Dictionaries.GetDictionariesAsync();
Dictionaries.FindDictionaryAsync(alias) Alias словаря. Task<CmsTagDictionary?>. var brands = await Dictionaries.FindDictionaryAsync("brands");
Dictionaries.GetValuesAsync(dictionaryAlias) Alias словаря. Task<IReadOnlyList<CmsTag>>. var brands = await Dictionaries.GetValuesAsync("brands");
Dictionaries.SearchValuesAsync(dictionaryAlias, search, take) Alias словаря, поисковая строка, лимит 1-100. Task<IReadOnlyList<CmsTag>>. Ищет по имени, alias и slug-транслитерации. var found = await Dictionaries.SearchValuesAsync("brands", "автоваз");
Dictionaries.FindValueAsync(dictionaryAlias, valueAlias) Alias словаря и alias значения. Task<CmsTag?>. var brand = await Dictionaries.FindValueAsync("brands", "avtovaz");

Настройки сайта

Метод Параметры Возвращает Пример
Settings.FindAsync(groupAlias, settingAlias) Alias группы и alias настройки. Task<CmsSetting?> с метаданными и ValueJson. var setting = await Settings.FindAsync("site", "phone");
Settings.GetAsync<T>(groupAlias, settingAlias) Alias группы, alias настройки, optional token. Task<T?>. Если значения нет, вернется default. var title = await Settings.GetAsync<string>("site", "title");

Для GetAsync<string> возвращается сохраненное значение как строка. Для чисел, bool и JSON-значений можно использовать типизированный GetAsync<T>. Если настройка хранится как дата/время в редакторском формате, берите строку или FindAsync и парсите ValueJson явно. Для настройки типа Tags удобнее получить CmsSetting через FindAsync и вызвать setting.GetTags().

URL и slug helpers

Метод Параметры Возвращает
Urls.NormalizePath(path) string? path. Нормализованный путь вида /docs/page.
Slugs.GenerateSlug(value) Любая строка. Slug в латинице: русские символы транслитерируются, лишние разделители убираются.

SEO aliases

Системные SEO-поля доступны через константы CmsSystemAttributeAliases.SeoTitle, SeoDescription, CanonicalUrl, Robots. В админке они отображаются только у шаблонов с включенной галочкой SEO параметры. Если значение не задано, Get<string> просто вернет null.

Пример

@model PageCharmPageModel
@inject IPageCharmContentQuery Content
@inject IPageCharmDictionaryQuery Dictionaries
@inject IPageCharmSettings Settings

@{
    var siteTitle = await Settings.GetAsync<string>("site", "title") ?? "PageCharm";
    var brands = await Dictionaries.GetValuesAsync("brands");

    var breadcrumbs = await Content.Active()
        .GetBreadcrumbsAsync(Model.Content);

    var baseQuery = Content.Active()
        .FromBlocks("catalog", "special-offers")
        .WithTemplates("product", "promo-card")
        .SearchFields("ноутбук", "title", "description")
        .WhereDecimalFieldBetween("price", min: 1000m, max: 250000m);

    var total = await baseQuery.CountAsync();

    var items = await baseQuery
        .OrderByField("price", CmsContentFieldSortType.DecimalNumber)
        .Skip(0)
        .Take(12)
        .ToListAsync();
}

<title>@(Model.Content.Get<string>(CmsSystemAttributeAliases.SeoTitle) ?? Model.Content.Name)</title>

<nav>
    <a href="/">Главная</a>
    @foreach (var parent in breadcrumbs)
    {
        <a href="@parent.Url">
            @(parent.Get<string>("title") ?? parent.Name)
        </a>
    }
</nav>

<h1>@siteTitle</h1>
<p>Найдено: @total</p>

@foreach (var item in items)
{
    var cover = item.GetFirstMedia("cover");
    <article>
        @if (cover is not null)
        {
            <img src="@cover.GetPresetUrl("kartochka-tovara")" alt="@cover.Alt">
        }
        <h2><a href="@item.Url">@(item.Get<string>("title") ?? item.Name)</a></h2>
        <strong>@item.Get<decimal>("price")</strong>
    </article>
}

Слой для public-сайта

Во вьюшках лучше читать CMS через IPageCharmContentQuery и helpers. EF Core напрямую оставьте для админки, миграций и специальных сервисов приложения.