Как реализовать API versioning в ASP.NET Core? Какие подходы существуют?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Реализация API Versioning в ASP.NET Core
API Versioning — критически важный компонент для долгосрочной поддержки и развития любого веб-сервиса. В ASP.NET Core существует несколько официальных и общепринятых подходов к управлению версиями API, каждый со своими преимуществами и сценариями использования.
Основные подходы к версионированию API
ASP.NET Core поддерживает следующие стратегии версионирования, которые можно использовать отдельно или комбинировать:
-
URI Path Versioning (Версионирование в пути URL) Самый распространенный и явный подход. Версия указывается непосредственно в пути запроса.
[ApiVersion("1.0")] [Route("api/v{version:apiVersion}/[controller]")] public class ProductsController : ControllerBase { [HttpGet] public IActionResult Get() => Ok("Version 1.0"); } [ApiVersion("2.0")] [Route("api/v{version:apiVersion}/[controller]")] public class ProductsControllerV2 : ControllerBase { [HttpGet] public IActionResult Get() => Ok("Version 2.0"); } -
Query String Versioning (Версионирование через query параметр) Версия передается как параметр запроса. Менее явный, но сохраняет чистоту URI.
// Настройка в Startup.cs или Program.cs services.AddApiVersioning(options => { options.ApiVersionReader = new QueryStringApiVersionReader("api-version"); }); // Контроллеры используют тот же маршрут [ApiVersion("1.0")] [Route("api/[controller]")] public class ProductsController : ControllerBase { } [ApiVersion("2.0")] [Route("api/[controller]")] public class ProductsControllerV2 : ControllerBase { } -
Header Versioning (Версионирование через HTTP заголовок) Версия указывается в специальном HTTP заголовке. Полностью скрывает версию от URI.
services.AddApiVersioning(options => { options.ApiVersionReader = new HeaderApiVersionReader("x-api-version"); }); // Запрос клиента включает заголовок: x-api-version: 2.0 -
Media Type Versioning (Версионирование в Content-Type/Accept) Версия указывается в медиа-типе запроса или ответа (content negotiation).
services.AddApiVersioning(options => { options.ApiVersionReader = new MediaTypeApiVersionReader("v"); }); // Клиент отправляет заголовок: Accept: application/json;v=2.0
Практическая реализация с библиотекой Microsoft.AspNetCore.Mvc.Versioning
Для полноценного версионирования в ASP.NET Core наиболее часто используется официальная библиотека Microsoft.AspNetCore.Mvc.Versioning.
Шаг 1: Добавление зависимостей и базовой конфигурации
// Program.cs
builder.Services.AddApiVersioning(options =>
{
options.DefaultApiVersion = new ApiVersion(1, 0); // Версия по умолчанию
options.AssumeDefaultVersionWhenUnspecified = true; // Использовать default версию если не указана
options.ReportApiVersions = true; // Добавлять в ответ заголовок api-supported-versions
// Указание стратегии чтения версии
options.ApiVersionReader = ApiVersionReader.Combine(
new QueryStringApiVersionReader("api-version"),
new UrlSegmentApiVersionReader()
); // Комбинированный подход
});
builder.Services.AddVersionedApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV"; // Формат имени группы для Swagger
options.SubstituteApiVersionInUrl = true; // Автоматическая подстановка версии в URL
});
Шаг 2: Организация контроллеров с версиями
Существует два основных паттерна организации контроллеров:
А) Раздельные контроллеры для каждой версии
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/products")]
public class ProductsV1Controller : ControllerBase
{
[HttpGet]
public IActionResult Get() => Ok("Products V1");
}
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/products")]
public class ProductsV2Controller : ControllerBase
{
[HttpGet]
public IActionResult Get() => Ok("Products V2 with enhanced features");
}
Б) Один контроллер с методами для разных версий
[ApiVersion("1.0")]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/products")]
public class ProductsController : ControllerBase
{
[HttpGet]
[MapToApiVersion("1.0")]
public IActionResult GetV1() => Ok("V1 method");
[HttpGet]
[MapToApiVersion("2.0")]
public IActionResult GetV2() => Ok("V2 method");
}
Шаг 3: Депрекация старых версий и коммуникация с клиентами
[ApiVersion("1.0", Deprecated = true)] // Указание депрекации
[ApiVersion("2.0")]
public class ProductsController : ControllerBase { }
// В ответах автоматически добавляется заголовок:
// api-supported-versions: 1.0, 2.0
// api-deprecated-versions: 1.0
Дополнительные рекомендации и лучшие практики
- Комбинирование стратегий: Использование
ApiVersionReader.Combine()позволяет клиентам выбирать удобный для них метод указания версии. - Консистентность: В рамках одного API предпочтительно использовать единый подход (чаще URI Path или Query String).
- Минорные версии: Библиотека поддерживает минорные версии (
1.1,2.5), но их использование должно быть осмысленным. - Swagger/OpenAPI интеграция: Для автоматической генерации документации по версиям используйте
Swashbuckle.AspNetCoreс настройкой черезAddVersionedApiExplorer. - Ведение логов: Включайте версию API в логирование для анализа использования разных версий.
- Политика поддержки: Четко определяйте сколько предыдущих версий поддерживается и сроки депрекации.
Пример комплексной конфигурации
// Program.cs
builder.Services.AddApiVersioning(options =>
{
options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = true;
options.ReportApiVersions = true;
options.ApiVersionReader = ApiVersionReader.Combine(
new UrlSegmentApiVersionReader(),
new HeaderApiVersionReader("x-api-version"),
new QueryStringApiVersionReader("api-version")
);
})
.AddVersionedApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
// Контроллер
[ApiVersion("1.0")]
[ApiVersion("2.0", Deprecated = true)]
[ApiVersion("3.0")]
[Route("api/v{version:apiVersion}/orders")]
public class OrdersController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
// Логика с учетом версии
var version = HttpContext.GetRequestedApiVersion();
return Ok($"Orders API version {version}");
}
}
Выбор конкретного подхода зависит от требований проекта: публичные API часто используют URI Path Versioning для максимальной явности, внутренние или B2B API могут предпочесть Header Versioning для чистоты URL. Ключевой принцип — обеспечить обратную совместимость и четкую коммуникацию изменений клиентам.