Во время разработки ПО поднимается много интересных вопросов - мелких и не очень. Чтобы самому не забыть, да и другим разработчикам в помощь - буду выкладывать их здесь
Такую ошибку получил при попытке подключения отладчиком Visual Studio 2022 к удаленному контейнеру Docker (Ubuntu). В общем, решение оказалось простое:
В общем, очень странная ситуация. Поставил очередное обновление Windows (16 февраля 2026). После чего последовательно отвалились: Visual Studio 2015 (не может подключиться к TFS), а затем и все виртуальные машины на Oracle VirtualBox. Насчет Visual Studio - это, может быть, совпадение. А вот с виртуалками вообще не понятно. Сначала была ошибка WHvCapabilityCodeHypervisorPresent is FALSE! Make sure you have enabled the 'Windows Hypervisor Platform' feature. (VERR_NEM_NOT_AVAILABLE). VT-x is not available (VERR_VMX_NO_VMX). Я посмотрел - ну, каким-то образом включился Hyper-V. Отключил. Получил ошибку VERR_CPUM_INVALID_HWVIRT_CONFIG (см...
В предшествующей статье я рассказал про реализацию подключения к Keycloak на стороне тестового консольного приложения на .NET Core 8 (одного из вариантов такого подключения). Теперь вернусь к вопросу о настройке Keycloak. Настройку зон (realms), пользователей, ролей - это почти полностью пропускаю, там все очень просто. Единственно отмечу, что обязательно надо или убрать флаг "обязательное поле" у незаполненных полей пользователей, или заполнить эти поля. Иначе подключение под этим аккаунтом не пройдет, клиент получит ошибку на этапе аутентификации - "Account is not fully set up"...
В предшествующей статье я рассказал, как дополнил код сервиса ASP.NET Core 8 Web API, чтобы выполнялась авторизация по предоставленному токену доступа (JWT). Теперь посмотрим, как в обычном приложении .NET Core можно подключиться к Keycloak и раздобыть эти самые токены. Использовать буду библиотеку Duende.IdentityModel из одноименного NuGet-пакета. Странно, но альтернатив для C# / .NET Core на данный момент вроде как и нет. По крайней мере, для OpenID Connect - не нашел. Итак. Скопировал этот класс...
Еще весной 2025 затеял я переход на внешнюю подсистему аутентификации и авторизации. Выбрал для этого Keycloak - поддерживает по умолчанию нужные возможности, достаточно популярен, бесплатен, работает и под Windows, ресурсы жрет умеренно. У меня там немало всякого, но в первую очередь взялся за бэкенд. Итак, есть сервис ASP.NET Core 8, Web API, контроллер. Что нужно сделать? Вообще, тема безопасности в ASP.NET Core вроде и расписана хорошо, ан нет - полно мест, где без практики и раскопок документации и форумов, нихрена ничего не понятно...
Собственно, в процессе написания автотестов с WebApplicationFactory наткнулся на такую ошибку (см. заголовок). Для тестирования вызовов с авторизацией использовал собственную генерацию токенов JWT: public static class MockJwtTokens
{
public const string StaticIssuer = "MockIssuer"; public static string Issuer { get; } = StaticIssuer; //Guid.NewGuid().ToString();
// Random issuer public static SecurityKey SecurityKey { get; } static MockJwtTokens()
{
var key = new byte[32]; using (var rng = RandomNumberGenerator...
На самом деле, очень просто - например, используем вот такой конструктор: public Foo(ILogger<Foo> logger, IWebHostEnvironment env)
{
_logger = logger;
if(!env.IsDevelopment())
{
...
}
}
И вот бывает же такое. Пилим тесты с использованием WebApplicationFactory... Который уже проект, все примерно одинаково, все идет нормально... И тут, внезапно, ровно один проект начинает выдавать ошибку - но не просто так, а только при исполнении из pipeline Azure DevOps. Ошибка - на старте factory, System.InvalidOperationException : Solution root could not be located using application root. Ошибка, которую давным давно, еще с 6 .NET Core должны были, вроде как, побороть. А тут у нас .NET Core 8, причем соседний похожий проект в этом же solution исполняется вообще без проблем. Да, я прочитал документацию...
В общем, вопрос был в том, как задать опции сериализации / десериализации для Minimal API. Для контроллеров это делаю так: builder.Services.AddControllers(options =>
{
....
}).AddJsonOptions(options =>
{
// Убираем Camel-case style форматирования в JSON
options.JsonSerializerOptions.PropertyNamingPolicy = null;
}); А вот для Minimal API делаем так: builder.Services.ConfigureHttpJsonOptions(options =>
{
// Убираем Camel-case style форматирования в JSON
options...
В общем-то, задача простая, но на всякий случай, запишу для памяти. Итак, есть у нас интеграционный тест с xUnit и WebApplicationFactory. Но при этом нужно: 1) Получить лицензионный ключ AutoMapper, который сконфигурирован на проверяемом сервисе 2) Проверить стороннюю (не используемую на сервисе) конфигурацию AutoMapper Код у меня получился такой: // Arrange IConfiguration configuration = _factory.Services.GetRequiredService<IConfiguration>(); string? storedLicenseKey = configuration["AutoMapperLicenseKey"]; if (string.IsNullOrEmpty(storedLicenseKey))
throw new Exception("Не найден ключ лицензии AutoMapper"); using var scope = _factory...
Долго не мог понять, почему не подходит стандартная строка форматирования, например "HH:mm:ss". И "hh:mm:ss". И только почти случайно обнаружил, что работает оно так: Value.ToString("hh':'mm':'ss")
Дела делаются быстро, если под руками толковый пример кода. Собственно, лежит этот пример здесь: https://github.com/dotnet/EntityFramework.Docs/blob/live/samples/core/Testing/TestingWithoutTheDatabase/SqliteInMemoryBloggingControllerTest.cs. Статья про тестирование с EF Core (точнее, про одно из направлений тестирования) - здесь: https://learn.microsoft.com/en-us/ef/core/testing/testing-without-the-database. Как мне вообще понадобились такие интеграционные тесты? Ну, есть кой-какие моменты, которые хочется прояснить на уровне тестов. Например, обработка некоторых ошибок взаимодействия с базой. А, кстати...