Управление версиями веб-API Asp.net .core не работает для сегмента пути URL - PullRequest
0 голосов
/ 29 мая 2019

Я заранее искал свою проблему в различных источниках, но ответы не дали мне решения.

Я внедряю управление версиями веб-API на основе Url в проекте .net core 2.2 способом, представленным здесь . Версия, которую я использовал для управления версиями, является последней версией Microsoft.AspNetCore.Mvc.Versioning 3.1.2. Я также пытался понять, как это работает из следующих источников: source1 , source2 , source3 , source4 .

У меня есть ValueController с методом GET в папке с именем Initial и Value2Controller в папке с именем New. Обе папки являются подпапками папки «Контроллеры».

Структура выглядит следующим образом:

Маршрутизация в ValueController: [Route("api/v{version:apiVersion}/[controller]")]

и в Value2Controller это: [Route("api/v{version:apiVersion}/value")]

Я также установил options.EnableEndpointRouting = false; в Startup.cs и попытался вызвать api / v1 / value или api / v2 / value. Оба раза я получаю сообщение об ошибке: несколько действий совпадают. Он не может различить действия двух контроллеров.

Я пытался использовать services.AddApiVersioning(); без параметров и удалить AddVersionedApiExplorer. Это не работает. Единственное, что работает, это сдачи [Route("api/v{version:apiVersion}/[controller]")] в обоих контроллерах и выполните следующие вызовы API:

api/v1/value и api/v2/value2.

Конфигурация в моем файле startup.cs выглядит следующим образом:

services.AddApiVersioning(options =>
    {
        options.ReportApiVersions = true;
        options.AssumeDefaultVersionWhenUnspecified = true;
        options.DefaultApiVersion = new ApiVersion(1, 0);
        options.ApiVersionReader = new UrlSegmentApiVersionReader();
        options.UseApiBehavior = true;
    });            

services.AddVersionedApiExplorer(
    options =>
    {
        options.GroupNameFormat = "'v'VVV";
        options.SubstituteApiVersionInUrl = true;
        options.AssumeDefaultVersionWhenUnspecified = true;
        options.DefaultApiVersion = new ApiVersion(1, 0);
    });

Чего мне не хватает, чтобы позвонить либо api/v1/value или api/v2/value и перейти к правильному запросу?

1 Ответ

0 голосов
/ 31 мая 2019

После некоторой дополнительной отладки я наконец понял, почему это не работает, поэтому я публикую решение для всех, кто столкнется с подобной проблемой. Проблема была в наследовании контроллера.

Я создал CustomBaseController (который я почему-то полностью игнорировал как проблемный) с некоторыми методами глобальной обработки исключений, наследование происходит следующим образом:

[ApiVersionNeutral]
[Route("api/[controller]")]
[ApiController]
CustomBaseController : Controller

и

[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
ValuesController : CustomBaseController { // http method implementations}

[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/values")]
[ApiController]
ValuesController : CustomBaseController { // updated http method implementations}

Механизм управления версиями не соответствовал атрибуту [ApiVersionNeutral], хотя для меня имело смысл, что базовый контроллер вообще не нужно менять. Более того, у меня была только основная маршрутизация в базовом контроллере

Таким образом, я получил сообщение об ошибке «Сопоставлено несколько действий».

Я также обнаружил, что контроллер версии 1 может наследовать маршрутизацию от базового контроллера, и у него не было причин иметь там маршрутизацию. Для всех последующих контроллеров маршрутизация должна быть: [Route("api/v{version:apiVersion}/values")].

Рабочее решение вместе с первоначальной конфигурацией, указанной выше, выглядит следующим образом:

[Route("api/v{version:ApiVersion}/[controller]")]
[ApiController]
CustomBaseController: Controller {}

[ApiVersion("1.0")]
[ApiController]
ValuesController: CustomBaseController { //code }


[ApiVersion("2.0")]
[ApiController]
[Route("api/v{version:ApiVersion}/values")]
Values2Controller: CustomBaseController { //code }

[ApiVersion("3.0")]
[ApiController]
[Route("api/v{version:ApiVersion}/values")]
Values3Controller: CustomBaseController { //code }

Получение значений из следующих URL:

api/v1/values
api/v2/values
api/v3/values

Несмотря на то, что моя проблема была решена, я все еще не понимаю, почему [ApiVersionNeutral] может привести к тому, что маршрутизация не сможет правильно определять версии других контроллеров. Любое объяснение будет высоко оценено. Спасибо @Matt Stannett за ваши комментарии, они привели меня в правильном направлении.

...