Для создания серверных модулей расширения к Pilot-Server требуется один из следующих выпусков Visual Studio
Чтобы создать новое расширение для Pilot-Server выполните следующие действия:
.servext Например PilotServerExtension.servextAssembly Information... и заполните необходимые поля.Обязательно заполните поля Title, Product и Assembly version, т.к. Pilot-Server при загрузке вашего расширения будет искать информацию именно в этих полях.
Для удобства отладки проекта серверного расширения, сборка может быть размещена в папке [path]\Development, где [path] - это путь, по которому размещен исполняемый файл Pilot-Server,
в данном случае установка серверного расширения через клиентское приложение не потребуется и расширение будет загружено при запуске Pilot-Server (папка Development по умолчанию отсутствует, ее необходимо создать).
Для подключения SDK Pilot к проекту расширения можно воспользоваться встроенным в Visual Studio механизмом распространения пакетов - NuGet Packages Manager.
Для того, чтобы подключить SDK с помощью Nuget Package Manager выполните следующие шаги:
Выполните команду:
Install-Package Ascon.Pilot.ServerExtensions.SDK
Щелкните правой кнопкой мыши на проекте и вызовите команду Manage NuGet Packages;
Система расширений основана на стандартном механизме расширений приложений в .NET - Managed Extensibility Framework (MEF). SDK содержит ряд экспортируемых и импортируемых интерфейсов. К экспортируемым интерфейсам относятся интерфейсы, которые описывают тип расширения. К импортируемым интерфейсам относятся интерфейсы взаимодействия с клиентом и работы с данными.
Данный интерфейс позволяет добавить новое действие, доступное в серверных скриптах автоматизаций.
string IServerActivity.Name { get; };
Имя действия, используемое в скрипте автоматизации.
Task IServerActivity.RunAsync(IModifierBase modifier, IModifierBackend backend, IServerActivityContext serverActivityContext, IAutomationEventContext automationEventContext);
Асинхронный метод обработки запуска действия.
где:
modifier - модификатор, позволяющий вносить изменения в объекты;backend - обеспечивает доступ к данным системы;serverActivityContext - контекст запуска действия, позволяющий получить параметры запуска действия;automationEventContext - контекст события, позволяющий определить объект-источник события и другую дополнительную информацию.Пример IServerActivity:
[Export(typeof(IServerActivity))]
public class SetLastWriteTimeActivity : IServerActivity
{
public string Name => "SetLastWriteTime";
public Task RunAsync(IModifierBase modifier, IModifierBackend backend, IServerActivityContext serverActivityContext, IAutomationEventContext automationEventContext)
{
modifier.EditObject(automationEventContext.Source).SetAttribute("LastWriteTime", DateTime.UtcNow);
return Task.CompletedTask;
}
}
Контекст запуска действия, позволяющий получить параметры запуска действия.
Dictionary<string, object> IServerActivityContext.Params { get; }
Словарь параметров запуска действия, заданных в json скрипта автоматизации.
List<string> IServerActivityContext.SourceTypes { get; }
Список типов, заданных в json скрипта автоматизации, для которых должно выполняться действие.
TargetType? IServerActivityContext.Target { get; }
Определяет, должно ли действие быть применено к объекту-источнику события либо к связанным с ним объектам.
RelationType? IServerActivityContext.RelationType { get; }
Определяет, к каким типам связанных объектов должно применяться действие (применимо только в случае IServerActivityContext.Target==TargetType.Relations).
RelationFilterByChangeKind? IServerActivityContext.RelationFilterByChangeKind { get; } { get; }
Определяет, должно ли применяться действие ко всем связанным объектам, или же только к добавленным или удаленным.
Dictionary<string, string> IServerActivityContext.Errors { get; }
Список ошибок при разборе json действия.
T GetService<T>() where T : class;
Получение дополнительных сервисов. В текущей версии доступно получение следующих сервисов:
var notifier = serverActivityContext.GetService<IAutomationNotifier>();
Сервис IAutomationNotifier служит для отправки уведомлений пользователям.
void Notify(int personId, INObject obj, string message, string notificationName);
где:
personId - идентификатор пользователя, которому будет отправлено уведомление;obj - объект, по которому будет создано уведомление. При клике пользователем по всплывающему уведомлению будет осуществлен переход к данному объекту;message - текст сообщения уведомления;notificationName - внутреннее имя канала уведомлений. Доступно для получения на стороне клиентского SDK обработки уведомлений;var fileHandler = serverActivityContext.GetService<IAutomationFileProvider>();
Сервис IAutomationFileProvider служит для получения файлов из файлового архива.
Метод проверки существования файла в файловом архиве.
bool Exists(Guid fileId);
где:
fileId - идентификатор файла; Асинхронный метод открытия файла на чтение.
Task<Stream> OpenReadAsync(Guid id);
где:
fileId - идентификатор файла; Контекст события-триггера действия.
INObject IAutomationEventContext.Source { get; }
Объект-источник события.
IEnumerable<INChange> IAutomationEventContext.Changes { get; }
Набор изменений, в результате которого сработал триггер. Включает в себя изменение по объекту-источнику события, если он был изменен.
INPerson IAutomationEventContext.InitiatingPerson { get; }
Пользователь-инициатор события.
DateTime IAutomationEventContext.EventDate { get; }
Время наступления события в формате UTC.
Данный интерфейс позволяет добавить обработчик, добавляющий дополнительную информацию к записи журнала пользовательских действий
string ProcessEvent(IModifierBackend backend, IBaseEventContext context);
Метод обработки новой записи журнала пользовательских действий
где:
backend - обеспечивает доступ к данным системы;context - контекст, дающий информацию о записи в журнал. Ниже перечислены возможные варианты контекстов.Контекст записи об изменении/добавлении орагнизационной единицы
EventKind EventKind { get; }
Тип события
DateTime ServerDateTime { get; }
Серверная дата записи изменения
string Login { get; }
Логин пользователя от имени которого произошло изменение
string IpAddress { get; }
IP адрес ПК с котрого инициировалось изменение
INOrganisationUnit IPositionChangedContext.Created { get; }
Созданная организационная единица
INOrganisationUnit IPositionChangedContext.Updated { get; }
Измененнная организационная единица
Контекст записи об изменении назначения или снятия пользователя с должности
EventKind EventKind { get; }
Тип события
DateTime ServerDateTime { get; }
Серверная дата записи изменения
string Login { get; }
Логин пользователя от имени которого произошло изменение
string IpAddress { get; }
IP адрес ПК с котрого инициировалось изменение
INPersonOnPositionData IPersonPositionChangedContext.INPersonOnPositionData { get; }
Данные об назначнии/ снятии пользователя с должности
Контекст записи об изменении объектов
EventKind EventKind { get; }
Тип события
DateTime ServerDateTime { get; }
Серверная дата записи изменения
string Login { get; }
Логин пользователя от имени которого произошло изменение
string IpAddress { get; }
IP адрес ПК с котрого инициировалось изменение
Guid IChangesetContext.ObjectId { get; }
Идентификатор объекта
IReadOnlyList<INChange> IChangesetContext.Changes { get; }
Изменения, произведенные над объектом
string IChangesetContext.ErrorString { get; }
Текст ошибки, если изменение не было принято
Контекст записи захвата/освобождения лицензии
EventKind EventKind { get; }
Тип события
DateTime ServerDateTime { get; }
Серверная дата срабатывания события
string Login { get; }
Логин пользователя
string IpAddress { get; }
IP адрес ПК пользователя
int LicenseType { get; }
Тип лицензии
int PersonId { get; }
Идентификатор пользователя
Контекст файла
EventKind EventKind { get; }
Тип события
DateTime ServerDateTime { get; }
Серверная дата срабатывания события
string Login { get; }
Логин пользователя
string IpAddress { get; }
IP адрес ПК пользователя
Guid ObjectId { get; }
Идентификатор объекта
string ObjectTitle { get; }
Отображаемое наименование объекта
int TypeId { get; }
Идентификатор типа
Guid FileId { get; }
Идентификатор файла
int PersonId { get; }
Идентификатор пользователя
Контекст версии
EventKind EventKind { get; }
Тип события
DateTime ServerDateTime { get; }
Серверная дата записи изменения
string Login { get; }
Логин пользователя от имени которого произошло изменение
string IpAddress { get; }
IP адрес ПК с котрого инициировалось изменение
Guid ObjectId { get; }
Идентификатор объекта
int DeletedSnapshotsCount { get; }
Количество удаленных версий
Контекст события аутентификации
EventKind EventKind { get; }
Тип события
DateTime ServerDateTime { get; }
Серверная дата события
string Login { get; }
Логин пользователя
string IpAddress { get; }
IP адрес ПК с котрого происходила аутентификация
string Message { get; }
Сообщение обо ошибке при неудачной аутентификации
Контекст записи об изменении конфигурации базы данных (типы, атрибуты, состояния, автоматизации)
EventKind EventKind { get; }
Тип события
DateTime ServerDateTime { get; }
Серверная дата записи изменения
string Login { get; }
Логин администратора от имени которого произошло изменение
string IpAddress { get; }
IP адрес ПК с котрого инициировалось изменение
Контекст записи об изменении учетных данных пользователя (поля интерфейса INPerson: Login, DisplayName, Comment, Sid, UidDn, Email, Phone, IsDeleted, IsAdmin, IsInactive)
EventKind EventKind { get; }
Тип события
DateTime ServerDateTime { get; }
Серверная дата записи изменения
string Login { get; }
Логин от имени которого произошло изменение
string IpAddress { get; }
IP адрес ПК с котрого инициировалось изменение
int PersonId { get; }
Идентификатор изменяемого пользователя
IReadOnlyList<IPersonChangeData> PersonChangeData { get; }
Данные об изменениях, содержащие наименование измененного поля, его старое и новое значения
Данный интерфейс предоставляет события для отслеживания метрик Pilot-Server
event EventHandler<ConnectionCountChangedEventArgs> ConnectionCountChanged;
Событие об изменении количества клиентских подключений к Pilot-Server. Учитываются подключения от всех клиентов, в т.ч. Pilot-myAdmin и сторонние сервисы.
event EventHandler<AuthEventArgs> OnUserAuth;
Событие уведомляет о аутентификации пользователя. В случае неуспешной аутентификации в аргументах события свойство IsSuccess будет установлено в false и заполнено свойство Exception.
event EventHandler<AuthEventArgs> OnAdministratorAuth;
Событие уведомляет о аутентификации администратора Pilot-Server. В случае неуспешной аутентификации в аргументах события свойство IsSuccess будет установлено в false и заполнено свойство Exception.
event EventHandler<SessionEventArgs> OnSessionClosed;
Событие уведомляет о завершении пользовательской сессии. Дальшейшая работа пользователя или администратора будет возможна только после повторной аутентификации.
event EventHandler<ChangesetEventArgs> OnChangeset;
Событие уведомляет о новом статусе набора изменений. Наборы изменений используются для изменения объектов Pilot и являются атомарными (либо все изменения набора будут приняты сервером, либо весь набор изменений будет отклонен).
Члены класса аргументов события ChangesetEventArgs:
Guid ChangesetIdentity { get; }Идентификатор набора изменений
ChangesetStatus Status { get; }Статус набора изменений. Enqueued - добавлен в очередь на обработку, Completed - успешно обработан, Error - не принят сервером (см. ошибку в ChangesetEventArgs.Error).
Exception Error { get; }Ошибка при применении набора изменений. Заполнена только в случае, если статус набора изменений Error.
event EventHandler<LicenseEventArgs> LicenseConsumed;
Событие уведомляет об успешном взятии лицензии пользователем.
event EventHandler<LicenseConsumeErrorEventArgs> LicenseConsumeError;
Событие уведомляет об ошибке при взятии лицензии пользователем.
event EventHandler<LicenseEventArgs> LicenseReleased;
Событие уведомляет о том, что взятая ранее лицензия была освобождена.
var searchService = serverActivityContext.GetService<IAutomationSearchService>();
Сервис IAutomationSearchService служит для поиска объектов. Порядок работы с интерфейсом IQueryBuilder описан в документации Ascon Pilot Server SDK
Метод поиска объектов.
IEnumerable<Guid> Search(IQueryBuilder queryBuilder, int maxResults = int.MaxValue);
где:
queryBuilder - конструктор запроса;maxResults - ограничение на количество возвращаемых результатов;Пример использования:
using System;
using System.Linq;
using System.Collections;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using Ascon.Pilot.ClientCore.Search;
...
namespace SearchActivitySample
{
[Export(typeof(IServerActivity))]
public class SearchActivity : IServerActivity
{
public string Name => "SearchActivity";
...
public Task RunAsync(IModifierBase modifier, IModifierBackend backend, IServerActivityContext serverActivityContext, IAutomationEventContext automationEventContext)
{
var searchService = serverActivityContext.GetService<IAutomationSearchService>();
var queryBuilder = QueryBuilderFactory.CreateEmptyQueryBuilder();
// пример поиска проектов, где указан контрагент
queryBuilder.Must(AttributeFields.String("Contractor_name").Exists());
IEnumerable<Guid> objectsWithContractors = searchService.Search(queryBuilder);
...
return Task.CompletedTask;
}
}
}
Интерфейс IServerApiFactory предназначен для регистрации дополнительных контрактов для клиент-серверного взаимодействия. Принцип работы с IServerApiFactory демонстрируется в примере Server\Extensions\Samples\ServerApiFactory.ServerExtension.