Разработка плагинов для веб-сервера
В этой статье рассмотрим написание плагина для WEB-версии ПОЛИНОМ:MDM.
Расположение ключевых элементов
Полный код версии проекта плагина располагается по пути: \SDK\Web\Samples\Server\Samples.WebApi.Plugin, а также будет приведён в конце статьи
Производить сборку плагина нужно в ту директорию, где у вас располагается файл PolynomWebServer.exe для запуска веб-сервера. Рядом с этим exe-файлом находятся библиотеки, которые необходимы для компиляции плагина:
- Ascon.Polynom.Api.dll
- Ascon.Polynom.Web.Api.Core.dll
- Ascon.Polynom.Web.Api.Plugins.Basic.dll
Предположим, у Вас это директория C:\POLYNOM\WebServer
В этой директории же в итоге должны будут появиться файлы созданного плагина, при запуске сервера плагины подключатся и будут доступны в Swagger'е.
В файле настроек проекта (в рассматриваемом примере это файл Samples.WebApi.Plugin.csproj) нужно указать пути до вышеупомянутых библиотек. Замените значения в тегах <HintPath>...</HintPath> на свои:
<ItemGroup>
<Reference Include="Ascon.Polynom.Api">
<HintPath>C:\POLYNOM\WebServer\Ascon.Polynom.Api.dll</HintPath>
<ExcludeAssets>All</ExcludeAssets>
<PrivateAssets>All</PrivateAssets>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Ascon.Polynom.Web.Api.Core">
<HintPath>C:\POLYNOM\WebServer\Ascon.Polynom.Web.Api.Core.dll</HintPath>
<ExcludeAssets>All</ExcludeAssets>
<PrivateAssets>All</PrivateAssets>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Ascon.Polynom.Web.Api.Plugins.Basic">
<HintPath>C:\POLYNOM\WebServer\Ascon.Polynom.Web.Api.Plugins.Basic.dll</HintPath>
<ExcludeAssets>All</ExcludeAssets>
<PrivateAssets>All</PrivateAssets>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
В том же файле Samples.WebApi.Plugin.csproj по аналогии нужно указать, куда будет помещён плагин после сборки (значение в теге <OutputPath>) :
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Library</OutputType>
<ImplicitUsings>disable</ImplicitUsings>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<OutputPath>C:\POLYNOM\WebServer</OutputPath>
</PropertyGroup>
Настройка методов и входных данных в Swagger'е
В основном файле проекта будут написаны методы, которые мы увидим в Swagger'е после запуска сервера.
Рассмотрим детально пример плагина из SDK (файл SampleController.cs):
/// <summary>
/// Возвращает статистику хранилища данных.
/// </summary>
/// <param name="referenceName">Если указано имя справочника, то статистика будет выдана только по этому справочнику.</param>
/// <param name="cancellationToken">Токен отмены.</param>
[HttpGet(nameof(GetStatistics))]
public async Task<ActionResult<CountInfo>> GetStatistics(string referenceName, CancellationToken cancellationToken)
Сначала идёт отображаемое описание метода: Возвращает статистику хранилища данных.
Далее описания для входных параметров: <param name="referenceName">Если указано имя справочника, то статистика будет выдана только по этому справочнику.</param>
Далее задаётся отображаемое имя метода: GetStatistics, оно также дублируется в названии функции в следующей строке
Task<ActionResult<...>> - базовая обёртка для выходных данных, а CountInfo - непосредственно полезное возвращаемое содержимое (в данном примере класс, описанный в файле Data\CountInfo.cs)
И в конце перечисляются входные атрибуты (в данном случае referenceName и cancellationToken)
Запуск и проверка
Теперь выполним сборку плагина. Для рассматриваемого примера результатом будет 4 файла, которые будут созданы в папке Bin\WebServer:
- Sample.Web.Api.Plugin.deps
- Sample.Web.Api.Plugin.dll
- Sample.Web.Api.Plugin.pdb
- Sample.Web.Api.Plugin.xml
Затем выполняем запуск сервера из той же директории, как результат у нас должен появиться новый раздел Sample в Swagger'е, который содержит метод get-statistics
Параметр api-version добавлен автоматически Swagger'ом и может быть проигнорирован.
Все файлы проекта плагина
Samples.WebApi.Plugin.csproj - файл настроек проекта:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Library</OutputType>
<ImplicitUsings>disable</ImplicitUsings>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<OutputPath>..\..\..\..\..\Bin\WebServer</OutputPath>
</PropertyGroup>
<PropertyGroup>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<PropertyGroup>
<RootNamespace>Sample.Web.Api.Plugin</RootNamespace>
<AssemblyName>Sample.Web.Api.Plugin</AssemblyName>
</PropertyGroup>
<PropertyGroup>
<Title>Пример дополнения к WEB API ПОЛИНОМ:MDM</Title>
<AssemblyTitle>$(Title)</AssemblyTitle>
<AssemblyDescription>$(Title)</AssemblyDescription>
<DocumentationFile>$(AssemblyName).xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0"/>
</ItemGroup>
<ItemGroup>
<Reference Include="Ascon.Polynom.Api">
<HintPath>..\..\..\..\..\Bin\WebServer\Ascon.Polynom.Api.dll</HintPath>
<ExcludeAssets>All</ExcludeAssets>
<PrivateAssets>All</PrivateAssets>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Ascon.Polynom.Web.Api.Core">
<HintPath>..\..\..\..\..\Bin\WebServer\Ascon.Polynom.Web.Api.Core.dll</HintPath>
<ExcludeAssets>All</ExcludeAssets>
<PrivateAssets>All</PrivateAssets>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Ascon.Polynom.Web.Api.Plugins.Basic">
<HintPath>..\..\..\..\..\Bin\WebServer\Ascon.Polynom.Web.Api.Plugins.Basic.dll</HintPath>
<ExcludeAssets>All</ExcludeAssets>
<PrivateAssets>All</PrivateAssets>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<ItemGroup>
<None Remove="Sample.Web.Api.Plugin.xml" />
<Content Include="Sample.Web.Api.Plugin.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
Controllers\SampleController.cs - основной файл с методами для Swagger'а и логикой исполнения
using Ascon.Polynom.Web.Api.Core.Interfaces;
using Ascon.Polynom.Web.Api.Plugins.Basic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Sample.Web.Api.Plugin.Data;
namespace Sample.Web.Api.Plugin.Controllers
{
/// <summary>
/// Пример контроллера расширения.
/// </summary>
[ApiController]
[Route("[controller]")]
[Authorize]
public class SampleController : WebApiPluginController
{
/// <summary>
/// Инициализирует экземпляр класса.
/// </summary>
public SampleController(IPolynomAuthorizationService authorizationService,
IServiceProvider services) : base(authorizationService, services)
{
}
/// <summary>
/// Возвращает статистику хранилища данных.
/// </summary>
/// <param name="referenceName">Если указано имя справочника, то статистика будет выдана только по этому справочнику.</param>
/// <param name="cancellationToken">Токен отмены.</param>
[HttpGet(nameof(GetStatistics))]
public async Task<ActionResult<CountInfo>> GetStatistics(string referenceName, CancellationToken cancellationToken)
{
return await Task.Run( async () =>
{
var result = new CountInfo();
var session = await GetPolynomApiSession(cancellationToken);
if (session is null)
return new JsonResult(result);
// Получение полного списка справочников.
var references = session.Objects.AllReferences;
foreach (var reference in references)
{
if (!string.IsNullOrEmpty(referenceName) && referenceName != reference.Name)
continue;
result.ReferenceCount++;
result.DocumentCatalogCount++;
result.ViewpointCatalogCount++;
foreach (var catalog in reference.Catalogs)
{
result.CatalogCount++;
}
}
// Получение списка понятий в корне.
var concepts = session.Objects.RootConcepts;
foreach (var concept in concepts)
{
result.RootConceptCount++;
// Получение списка вложенных понятий.
var innerConcepts = concept.AllSubConcepts;
foreach (var innerConcept in innerConcepts)
{
result.InnerConceptCount++;
}
}
// Получение списка групп определений свойств.
var propDefGroups = session.Objects.PropDefCatalog.PropDefGroups;
foreach (var propDefGroup in propDefGroups)
{
ProcesPropDefGroup(result, propDefGroup);
}
return new JsonResult(result);
}, cancellationToken
);
}
private void ProcesPropDefGroup(CountInfo countInfo, Ascon.Polynom.Api.IPropDefGroup propDefGroup)
{
countInfo.PropertyDefinitionGroupCount++;
// Получение списка определений свойств в группе.
foreach (var propDef in propDefGroup.PropertyDefinitions)
{
countInfo.PropertyDefinitionCount++;
}
// Получение списка вложенных групп определений свойств.
foreach (var innerPropDefGroup in propDefGroup.PropDefGroups)
{
ProcesPropDefGroup(countInfo, innerPropDefGroup);
}
}
}
}
Data\CountInfo.cs - вспомогательный файл, описывает выходную модель данных
namespace Sample.Web.Api.Plugin.Data;
/// <summary>
/// Представляет статистику хранилища.
/// </summary>
public class CountInfo
{
/// <summary>
/// Возвращает или задает количество справочников.
/// </summary>
public int ReferenceCount { get; set; }
/// <summary>
/// Возвращает или задает количество каталогов.
/// </summary>
public int CatalogCount { get; set; }
/// <summary>
/// Возвращает или задает количество каталогов документов.
/// </summary>
public int DocumentCatalogCount { get; set; }
/// <summary>
/// Возвращает или задает количество каталогов представлений.
/// </summary>
public int ViewpointCatalogCount { get; set; }
/// <summary>
/// Возвращает или задает количество понятий в корне.
/// </summary>
public int RootConceptCount { get; set; }
/// <summary>
/// Возвращает или задает количество вложенных понятий.
/// </summary>
public int InnerConceptCount { get; set; }
/// <summary>
/// Возвращает или задает количество групп определений свойств.
/// </summary>
public int PropertyDefinitionGroupCount { get; set; }
/// <summary>
/// Возвращает или задает количество определений свойств.
/// </summary>
public int PropertyDefinitionCount { get; set; }
}
Properties\launchSettings.json - вспомогательный файл проекта, изменения не требуются
{
"profiles": {
"Samples.WebApi.Plugin": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:59080;http://localhost:59081"
}
}
}