Поддерживая существующие уже какое-то время Web API проекты, мы нередко сталкиваемся с проблемой устаревания логики методов контроллеров и необходимостью ее изменения в соответствии с новыми требованиями. Но, как правило, на момент возникновения такой необходимости, уже существует определенное число сервисов, использующих текущую реализацию наших API, и не нуждающихся в ее модернизации. Более того, такие сервисы могут легко «сломаться» при изменении используемых ими API.
Для решения такого рода проблем в ASP.Net Core существует механизм версионирования API – когда контроллеры и их методы могут существовать одновременно в разных версиях. В таком случае, те сервисы, которым достаточно существующего состояния используемых ими API, могут продолжать использовать определенные версии этих API, а для сервисов, которые требуют модернизации логики контроллеров, мы можем создавать новые параллельные версии, и все эти версии могут работать в нашем проекте одновременно.
-
В Visual Studio создаем новый проект ASP.NET Core Web API:

-
В новый проект добавляем NuGet пакет: Microsoft.AspNetCore.Mvc.Versioning
Для этого в SolutionExplorer (Обозреватель решений) правой кнопкой мыши жмем по названию рабочего проекта и выбираем Manage NuGet Packages… (Управление пакетами Nuget).
Далее переходим на крайнюю левую вкладку Browse, и в строку поиска вводим название устанавливаемого пакета NuGet.
В левом окне выбираем нужный нам пакет, а в правом жмем кнопку Install.

-
В метод ConfigureServices класса Startup.cs добавляем строку «services.AddApiVersioning();»:
public void ConfigureServices(IServiceCollection services) { // другой код services.AddControllers(); services.AddApiVersioning(); // другой код }
-
В папке ‘Controllers’ создаем новую папку “V2”.
-
В созданную папку добавляем новый API контроллер:

И называем его WeatherForecastController, так же, как и созданный по умолчанию контроллер.
В новый контроллер добавляем логику уже существующего контроллера, и немного
изменяем ее. Также добавляем к контроллеру атрибут [ApiVersion(«2.0»)]
и в атрибуте Route изменяем маршрут:
[Route("api/v{version:apiVersion}/[controller]")] [ApiController] [ApiVersion("2.0")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Сильный мороз", "Мороз", "Холодно", "Прохладно", "Свежо", "Тепло", "Духота", "Жара", "Сильная жара" }; [HttpGet] public IEnumerable<WeatherForecast> Get() { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-40, 40), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } }
Маршрут нового контроллера теперь будет: «/api/v2/WeatherForecast».
-
К автоматически созданному с проектом контроллеру добавим атрибут [ApiVersion(«1.0»)]:
[ApiController] [Route("[controller]")] [ApiVersion("1.0")] public class WeatherForecastController : ControllerBase { // созданная по умолчанию логика }
Таким образом, мы имеем две версии по сути одного контроллера – 1 и 2.
Маршрут вызова первого контроллера остается прежним, но теперь мы обязаны сообщить маршрутизатору нужную нам версию.
Передать версию контроллера можно несколькими способами:
-
в параметрах запроса: https://localhost:44335/WeatherForecast?api-version=1.0
-
в HTTP заголовках запроса. Для этого нужно видоизменить метод AddApiVersioning в методе ConfigureServices класса Startup.cs:
services.AddApiVersioning(config => { config.ApiVersionReader = new HeaderApiVersionReader("api-version"); });
и добавить в запрос соответствующий заголовок:

-
в URL запроса: https://localhost:44335/api/v2/WeatherForecast
-
Вызовем метод первого контроллера. Для этого воспользуемся способом передачи версии через параметры запроса.
Запустим наш проект, и в браузере или инструменте для работы с API (Postman, Insomnia и т.д.) введем Url: “https://localhost:44335/WeatherForecast?api-version=1.0”. Разумеется, порт нужно указывать соответствующий вашему приложению.
Получим результат:
[ { "date":"2022-02-06T00:22:54.6248567+06:00", "temperatureC":-13, "temperatureF":9, "summary":"Scorching" }, { "date":"2022-02-07T00:22:54.6261864+06:00", "temperatureC":24, "temperatureF":75, "summary":"Freezing" }, { "date":"2022-02-08T00:22:54.6261919+06:00", "temperatureC":-12, "temperatureF":11, "summary":"Freezing" }, { "date":"2022-02-09T00:22:54.6261927+06:00", "temperatureC":40, "temperatureF":103, "summary":"Sweltering" }, { "date":"2022-02-10T00:22:54.6261931+06:00", "temperatureC":27, "temperatureF":80, "summary":"Balmy" } ]
8. Вызовем метод второго контроллера. Для этого воспользуемся способом передачи версии в Url запроса, так как мы задали его с помощью атрибута [Route(«api/v{version:apiVersion}/[controller]»)] и должны теперь ему следовать.
Запустим наш проект, и в браузере или инструменте для работы с API (Postman, Insomnia и т.д.) введем Url: “https://localhost:44335/api/v2/WeatherForecast”.
Получим результат:
[ { "date":"2022-02-06T00:32:43.5572436+06:00", "temperatureC":27, "temperatureF":80, "summary":"Жара" }, { "date":"2022-02-07T00:32:43.5577678+06:00", "temperatureC":14, "temperatureF":57, "summary":"Сильная жара" }, { "date":"2022-02-08T00:32:43.5577702+06:00", "temperatureC":15, "temperatureF":58, "summary":"Тепло" }, { "date":"2022-02-09T00:32:43.5577706+06:00", "temperatureC":0, "temperatureF":32, "summary":"Духота" }, { "date":"2022-02-10T00:32:43.5577707+06:00", "temperatureC":-14, "temperatureF":7, "summary":"Тепло" } ]
-
Вызов первого контроллера по его первоначальному маршруту без указания версии — https://localhost:44335/WeatherForecast
Предположим, что первый контроллер уже используется несколькими другими проектами (сервисами) в его первоначальном виде, каким он был до добавления в проект версионирования, и никто не собирается рефакторить эти проекты и менять Url для вызова. Они по-прежнему обращаются к нашему API по маршруту “https://localhost:44335/WeatherForecast”.
В таком случае, мы задаем версию по умолчанию, и если версия в запросе не будет указана, то запрос направляется на заданную версию.
Для этого изменим метод AddApiVersioning в методе ConfigureServices класса Startup.cs:
services.AddApiVersioning(config => { config.DefaultApiVersion = new ApiVersion(1, 0); config.AssumeDefaultVersionWhenUnspecified = true; });
В данном случае, все запросы, в которых не указана версия, будут направляться на контроллер первой версии. Теперь мы можем вызывать первый контроллер по его первоначальному маршруту, он будет работать.
-
Мы можем отметить первую версию как устаревшую, немного изменив атрибут версии: [ApiVersion(«1.0», Deprecated = true)]
-
С помощью атрибута MapToApiVersion мы имеем возможность управлять версиями на уровне методов:
[MapToApiVersion("3.0")] [HttpGet] public int DoSomething() { // логика метода }
ссылка на оригинал статьи https://habr.com/ru/post/649827/
Добавить комментарий