← Назад к вопросам

Как реализовать API versioning в ASP.NET Core? Какие подходы существуют?

2.0 Middle🔥 161 комментариев
#ASP.NET и Web API

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализация API Versioning в ASP.NET Core

API Versioning — критически важный компонент для долгосрочной поддержки и развития любого веб-сервиса. В ASP.NET Core существует несколько официальных и общепринятых подходов к управлению версиями API, каждый со своими преимуществами и сценариями использования.

Основные подходы к версионированию API

ASP.NET Core поддерживает следующие стратегии версионирования, которые можно использовать отдельно или комбинировать:

  1. 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");
    }
    
  2. 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 { }
    
  3. Header Versioning (Версионирование через HTTP заголовок) Версия указывается в специальном HTTP заголовке. Полностью скрывает версию от URI.

    services.AddApiVersioning(options =>
    {
        options.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
    });
    
    // Запрос клиента включает заголовок: x-api-version: 2.0
    
  4. 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. Ключевой принцип — обеспечить обратную совместимость и четкую коммуникацию изменений клиентам.

Как реализовать API versioning в ASP.NET Core? Какие подходы существуют? | PrepBro