SDK (Portal.EventReceiver.Sdk)
C# SDK для разработки Event Receiver.
Настройка SDK: Extension SDK с korport.ru/developers.
Интерфейс обработчика
Заголовок раздела «Интерфейс обработчика»using Portal.EventReceiver.Sdk;
public sealed class MyHandler : IEventReceiver{ public async Task<object?> HandleAsync( EventContext context, IReceiverApi api, CancellationToken cancellationToken = default) { // Текущий изменённый элемент (без ручного разбора Details) var item = await context.GetListItemAsync(api, cancellationToken); if (item is null) return new { skipped = true };
api.Log.Info("Updated item", context.GetItemRef(), item.GetString("title")); return new { ok = true }; }}EventContext
Заголовок раздела «EventContext»| Поле | Тип | Описание |
|---|---|---|
EventName | string | Имя события (listItem.updated и т.д.) |
Details | JsonElement | Данные события (listId, item, user) |
ReceiverConfig | JsonElement | Config привязки из UI (listId, note) |
User | EventUserInfo? | Пользователь, инициировавший событие |
Payload | JsonElement | Полный JSON задания |
Текущий элемент (EventContextExtensions)
Заголовок раздела «Текущий элемент (EventContextExtensions)»Для listItem.created / updated / deleted не разбирайте Details вручную:
| Метод | Описание |
|---|---|
IsListItemEvent() | Событие элемента списка |
GetListId() | GUID списка из details.listId |
GetItemRef() | Номер/GUID элемента (details.item.id или fallback на deleted) |
TryGetItemJson(out item) | Сырой снимок details.item |
GetListItemAsync(api) | Актуальный элемент с сервера → PortalListItem? |
GetListItemSnapshotAsync(api) | Элемент из снимка события (удобно для deleted) |
if (!context.IsListItemEvent()) return new { skipped = true };
var listId = context.GetListId();var itemRef = context.GetItemRef();
// created / updated — свежие данные с правами пользователя событияvar item = await context.GetListItemAsync(api, ct);var title = item?.GetString("title");
// deleted — элемент уже удалён; читайте снимок из событияif (context.EventName == "listItem.deleted"){ var snapshot = await context.GetListItemSnapshotAsync(api, ct); api.Log.Info("Deleted", snapshot?.GetString("title"));}EventUserInfo
Заголовок раздела «EventUserInfo»| Свойство | Тип | Описание |
|---|---|---|
Id | Guid | UUID пользователя |
Login | string? | Логин |
Receiver API (IReceiverApi)
Заголовок раздела «Receiver API (IReceiverApi)»| Объект | Метод | Описание |
|---|---|---|
Lists | GetAsync | Метаданные списка |
GetFieldsAsync | Схема полей | |
GetListItemAsync / NewListItemAsync / QueryListItemsAsync | SharePoint-подобный PortalListItem: item["title"], CreateAsync / UpdateAsync | |
GetItemAsync | Один элемент (сырой JSON) | |
GetItemVersionsAsync | История версий (fieldValues в каждой версии) | |
GetItemVersionAsync | Одна версия по номеру | |
GetItemsAsync / QueryItemsAsync | Выборка элементов (сырой JSON) | |
CreateItemAsync / UpdateItemAsync | Низкоуровневое создание / изменение (с проверкой прав) | |
Libraries | GetAsync | Метаданные библиотеки |
GetFilesAsync / QueryFilesAsync | Выборка файлов | |
Nodes | GetAsync | Узел |
Users | GetProfileAsync / GetOrgChainAsync / GetOrgChildrenAsync / AvatarUrl | Профиль сотрудника и оргструктура |
Permissions | ForListAsync / ForListItemAsync / GrantToUserAsync / RevokeAsync / … | Проверка и назначение ACL (детали) |
Kedo | CreatePackageAsync / GetPackageStatusAsync | Отправка документа на подпись/ознакомление (КЭДО) |
Jobs | EnqueueAsync(serviceKey, jobType, jobPayload?) | Поставить задание в очередь |
Log | Info / Warn / Error | Логирование Worker (params object[]) |
Права и ACL выполняются от имени пользователя из context.User.
Выборка элементов списка
Заголовок раздела «Выборка элементов списка»using Portal.Contracts.Lists;
// Fluent-builder (C# DLL)var items = await api.Lists.QueryItemsAsync(listId!, ListItemQueryBuilder.ForList(Guid.Parse(listId!)) .WhereField("title", f => f.Eq("GlobalSettings")) .Take(1) .Build(), cancellationToken);
// Объект opts (тот же формат, что query-параметры REST)var batch = await api.Lists.GetItemsAsync(listId!, new{ viewId, top = 50, orderBy = new[] { new { column = "title", direction = "asc" } }, filter = new { logic = "and", conditions = new[] { new { column = "title", op = "eq", value = "A" } }, }, q = "поиск",}, cancellationToken);column в фильтре — UUID поля или internal_name ("title"). Фильтрация выполняется на сервере (SQL push-down), см. API списков.
Выборка файлов библиотеки
Заголовок раздела «Выборка файлов библиотеки»using Portal.Contracts.Libraries;
var files = await api.Libraries.QueryFilesAsync(libraryId!, LibraryFileQueryBuilder.ForLibrary(Guid.Parse(libraryId!)) .InFolder(folderId) .WhereField("name", f => f.Contains("договор")) .Take(50) .Build(), cancellationToken);
// Объект opts (тот же формат, что query-параметры REST)var batch = await api.Libraries.GetFilesAsync(libraryId!, new{ parentId = folderId, top = 50, orderBy = new[] { new { column = "updated_at", direction = "desc" } }, filter = new { logic = "and", conditions = new[] { new { column = "item_type", op = "eq", value = "file" } }, }, q = "отчёт",}, cancellationToken);Колонки фильтра: name, item_type, file_size, mime_type, updated_at, created_at, uploaded_by, version_number, item_number. См. API библиотек.
PortalListItem — чтение и обновление полей
Заголовок раздела «PortalListItem — чтение и обновление полей»Рекомендуемый путь — текущий элемент события + доступ по internal_name (гайд):
using Portal.Contracts.Lists;using Portal.EventReceiver.Sdk;
var item = await context.GetListItemAsync(api, ct) ?? throw new InvalidOperationException("В событии нет listId/item");
var currentTitle = item.GetString("title");var status = item.GetString("status");
item["status"] = "Готово";await item.UpdateAsync(ct);
// Создание в том же спискеvar listId = context.GetListId()!.Value;var created = await api.Lists.NewListItemAsync(listId, ct);created["title"] = "Новая задача";created["status"] = "Новая";await created.CreateAsync(ct);
// Выборкаvar found = await api.Lists.QueryListItemsAsync(listId, ListItemQueryBuilder.ForList(listId) .WhereField("title", f => f.Eq("GlobalSettings")) .Take(1) .Build(), ct);Низкоуровнево (UUID / сырой JSON, версии) — GetItemAsync + field_values[fieldId] или PortalItemJson. Полные примеры: Значения полей списков.
Шаблон проекта
Заголовок раздела «Шаблон проекта»dotnet new install ./portal-sdk-1.0.0/templates/portal-eventreceiverdotnet new portal-eventreceiver -n MyHandler -o ./my-handlerПример в SDK ZIP: examples/list-change-handler. См. Extension SDK.