Перевод решений на .NET 8.0
Начиная с версии 6.1 сборки 170 и выше, Web-клиент работает на .NET 8.0, поэтому при переходе с Web-клиент, использующего .NET предыдущих версий, необходимо перевести на .NET 8.0 собственные решения.
Изменение файла проекта
-
При помощи автоматических инструментов (см. документацию Microsoft).
-
При помощи создания нового проекта, нацеленного на .NET 8. При создании проекта предпочтительно использовать шаблоны VisualStudio из примеров разработки расширений для версии 6.1.
В проектах нового типа нет необходимости добавлять файлы с исходным кодом в .csproj-файл проекта. По умолчанию автоматически все файлы в папке проекта считаются частью проекта. Это существенно упрощает процесс преобразования проекта.
Важной особенностью нового проекта является атрибут Sdk на корневом элементе Project файла .csproj, это xml-файл, который можно открыть в блокноте. Для web-расширений рекомендуется значение Microsoft.NET.Sdk.Web, для расширений конструктора разметок Microsoft.NET.Sdk.
Значение тега TargetFramework для web-расширений должно быть net8.0, для расширений конструктора разметок — net8.0-windows.
Для проектов расширений конструктора разметок также могут быть полезны следующие элементы:
<UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF>
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
Особенности сборки
Для сборки C# кода для .NET 8 требуется VisualStudio 2022 или старше.
При использовании сторонних зависимостей требуется обновить их до версий, поддерживающих .NET 8. В случае нарушений совместимости при сборке будет выдаваться предупреждение CA1416. Данные предупреждения следует все устранять.
При разработке расширений для программы Конструктор Web-разметок и другого кода, рассчитанного на работу в ОС Windows следует использовать атрибут SupportedOSPlatform. Его можно назначить на отдельный класс, либо на всю сборку:
[assembly: SupportedOSPlatform("windows")]
Без этого атрибута также может возникать предупреждение CA1416, при обращении к API, рассчитанному на работу в ОС Windows.
Логика привязки параметров в запросах
-
Метод контроллера либо принимает несколько параметров простых типов через query-параметры, либо один параметр, значение которого читается из тела запроса.
-
Рекомендуется явно указывать, откуда читается параметр с помощью атрибутов
[FromBody]и[FromQuery]. Если ранее использовался атрибутFromUri, то нужно заменить наFromQuery. -
Рекомендуется явно помечать методы атрибутами
[HttpGet],[HttpPost], для указания метода вызова
public class MathController : ControllerBase
{
[HttpGet]
public double GetSquare([FromQuery] double value) {
return
}
}
let result = await requestManager.get(`/Math/GetSquare?value=2`, null);
class MinValueParams {
public List<double> Values { get; set; };
}
public class MathController : ControllerBase
{
[HttpPost]
public double MinValue([FromBody] MinValueParams arg) {
return arg.Values.Min();
}
}
Если не указать [FromBody] для сложного параметра, его значение не привяжется.
|
let arg = { values: [ 1, 5, 3, 2] };
let result = await requestManager.post(`/Math/MinValue`, JSON.stringify(arg));
| При передаче параметра в теле запроса нельзя указывать имя параметра, т.к. он может быть только один. |
let data = { arg: { values: [ 1, 5, 3, 2] } }; (1)
let result = await requestManager.post(`/Math/MinValue`, JSON.stringify(data)); (2)
| 1 | Неверный код. |
| 2 | Код не будет работать. |
Внедрение зависимостей
В Web-клиенте 18 (6.1) вместо Autofac используется стандартный механизм внедрения зависимостей .NET. В связи с этим в классе серверного расширения нужно произвести следующие изменения:
InitializeContainer определить метод:public override void InitializeServiceCollection(IServiceCollection services)
{
(1)
}
| 1 | Регистрация сервисов. |
containerBuilder.RegisterType<YourServiceClass>().As<YourServiceInterface>().SingleInstance();
->
services.AddSingleton<YourServiceInterface, YourServiceClass>();
containerBuilder.RegisterOrderedType<YourBindingConverterType, IBindingConverter>();
->
services.AddSingleton<IBindingConverter, YourBindingConverterType>();
containerBuilder.RegisterOrderedType<YourBindingResolverType, IBindingResolver>();
->
services.AddSingleton<IBindingResolver, YourBindingResolverType>();
containerBuilder.RegisterOrderedType<YourControlResolverType, IControlResolver>();
->
services.AddSingleton<IControlResolver, YourControlResolverType>();
containerBuilder.RegisterOrderedType<YourPropertyResolverType, IPropertyResolver>();
->
services.AddSingleton<IPropertyResolver, YourPropertyResolverType>();
containerBuilder.RegisterType<YourCardLifeCycle>().Keyed<ICardLifeCycle>(CardTypeID).SingleInstance();
->
services.AddTransient<ICardLifeCycle, YourCardLifeCycle>();
containerBuilder.RegisterType<YourRowLifeCycle>().Keyed<IRowLifeCycle>(SectionID).SingleInstance();
->
services.AddTransient<IRowLifeCycle, YourRowLifeCycle>();
Прочие изменения
-
В конструкторе класса расширения при вызове базовой реализации теперь не нужно передавать
serviceProvider:Былоpublic ServerExtension(IServiceProvider serviceProvider) : base(serviceProvider) { }Сталоpublic ServerExtension(IServiceProvider serviceProvider) : base() { } -
Классы контроллеров рекомендуется наследовать от
Microsoft.AspNetCore.Mvc.ControllerBase. При переводе методыrequestManagergetиpostв некоторых случаях могут изменить возвращаемое значение. В частности, ранее они могли возвращать строку, а после перевода — объект — результатJSON.parseэтой строки. С примером можно ознакомиться ниже.Былоconst response = JSON.parse(await requestManager.get(url));Сталоconst response = await requestManager.get(url) -
Также в отдельных случаях может измениться регистр первой буквы в названии свойств ответа сервера. Например, следующим образом:
Былоconst name = response.IssueName;Сталоconst name = response.issueName; -
Изменился способ загрузки и скачивания файлов. Пример реализации соответствующего метода на .NET6 можно найти в примере
ExternalWebService, в файлеDocumentsController.cs, методахUploadFileиDownloadFile. -
Чтение настроек из конфигурационного файла Web-сервиса изменилось. Прежние сервисы оставлены для обратной совместимости, однако рекомендуется использовать стандартный механизм работы с настройками .NET 8. В частности, использовать внедрение интерфейса
IOptionsчерез конструктор для получения настройки иAddOptions+BindConfigurationпри регистрации сервисов для регистрации настройки. Пример работы с настройками можно найти в примереKonturIntegration(регистрация см.KonturServerExtension.cs/InitializeServiceCollection, чтение см.KonturRequestService.cs). -
Библиотека
iTextSharp, которая использовалась в примереWatermark, поддерживает .NET6 только в новой версии, под названиемitext7. В этой новой версии полностью изменился API.