Статический анализ генерируемой OpenApi-разметки и .NET 10
Привет, Хабр! 👋 На связи Саша Кузнецов, ведущий инженер-программист в Контуре.
Начиная с версии .NET 10 Microsoft решила поломать обратную совместимость в отношении статических анализаторов генерируемой OpenApi-разметки.
[HttpGet("{id}")] [ProducesResponseType<User>(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task<IActionResult> GetUser(int id) { var user = users.FirstOrDefault(p => p.Id == id); if (user == null) return NotFound(); return Ok(user); }
Раньше можно было возвращать IActionResult, или ActionResult, размечая типы ответов специальными атрибутами типа ProducesResponseType (см. код 1). Это позволяло включить потом статический анализатор добавлением в настройки проекта специального атрибута IncludeOpenAPIAnalyzers (см. код 2) и получать предупреждения на этапе компиляции, или статического анализа кода (см. код 3).
<PropertyGroup> <TargetFramework>net10.0</TargetFramework> <IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers> </PropertyGroup>

Увы, но с выходом .NET 10 этот подход был объявлен устаревшим (см.: https://learn.microsoft.com/ru-ru/aspnet/core/breaking-changes/10/openapi-analyzers-deprecated и https://github.com/aspnet/Announcements/issues/521). Microsoft решила сосредоточиться на работе через Results (см. код 4), которые появились в .NET 7. В них статический анализ поддерживается "из коробки" из-за строгой типизации.
[HttpGet("{id}")] public async Task<Results<Ok<User>, NotFound>> GetUser(int id) { var user = users.FirstOrDefault(p => p.Id == id); if (user == null) return TypedResults.NotFound(); return TypedResults.Ok(user); }
Сама тенденция не сильно радует. В старых проектах IActionResult и ActionResult (их пока не объявили устаревшими, но без статического анализа ошибок разметки они начнут терять привлекательность) используются много где.

