Разработчикам
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 напрямую оставьте для админки, миграций и специальных сервисов приложения.