ASP. NET Управление версиями контроллера Web Api 2. Маршрут не найден - PullRequest
0 голосов
/ 17 апреля 2020

У меня есть ASP. NET Приложение Web Api 2, в котором уже есть контроллеры. Теперь у нас есть новые контроллеры, которые нужно добавить, но с префиксом (v10)

/api/products/1          // Old controller
/api/v1/proucts/1        // the new controller

Я пытался создать версию API с атрибутом ApiVersion:

[ControllerName("Products")]
[ApiVersion("1.0")]
[RoutePrefix("api/v10/[controller]")]
public class ProductsV1Controller : ApiController
{
...
}

И старый контроллер:

public class ProductsController : ApiController
{
...
}

Маршрутизация без версии все еще работает и обращается к старому контроллеру, но когда я вызываю эту маршрутизацию:

api / v10 / products / 1

Возвращает 404 Страница не найдена. Один и тот же метод get написан на обоих контроллерах только для целей тестирования.

В моей конфигурации запуска:

httpConfig.MapHttpAttributeRoutes();

httpConfig.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: null);

Кто-нибудь знает, как настроить маршрутизацию для правильной навигации?

1 Ответ

0 голосов
/ 29 апреля 2020

@ Саджид был в основном правильно. При версии по сегменту URL необходимо использовать ограничение маршрута версии API. В игре есть пара вопросов. Похоже, вы переходите от неверсированного API к версионному API, что является поддерживаемым сценарием. Приведенные вами примеры значений не совпадают. Похоже, вы идете от v1 до v10. Значения не имеют значения, но следует понимать, что ваш существующий API имеет некоторое логическое имя, даже если вы никогда ранее не присваивали ему значение.

Проблема 1

Вы не сделали Не указывайте настройки, но это должно быть что-то вроде:

var constraintResolver = new DefaultInlineConstraintResolver()
{
  ConstraintMap = { ["apiVersion"] = typeof( ApiVersionRouteConstraint ) }
};
configuration.MapHttpAttributeRoutes( constraintResolver );
configuration.AddApiVersioning(
  options =>
  {
    // required because the original API doesn't have a version in the URL
    options.AssumeDefaultVersionWhenUnspecified = true;

    // this is already the default value, but you might need to change it.
    // this is the value that will be 'assumed' by the original, unversioned
    // API. it is addressable by /api/products. if you meant to start at 1.0,
    // then you can use a lower value such as 0.9
    options.DefaultApiVersion = new ApiVersion(1, 0);
  });

Проблема 2

Маркер [controller] не поддерживается в Web API. Эта концепция, наряду с [action], была введена в ASP. NET Базовая маршрутизация.

Вы не полностью уяснили, как вы решили проблему, но Ваши изменения почти наверняка подскажут, как смешивание стилей может сбивать с толку. Неясно, соответствовал ли API маршруту атрибута или маршруту на основе соглашения.

Проблема 3

Ваш шаблон маршрута не включает ограничение маршрута версии API (для получения информации о регистрации см. Проблема 1) , Это необходимо для того, чтобы API Versioning знал , как извлечь версию API из URL. Управление версиями API не делает волхвы c строка парсинг с регулярными выражениями, et c.

Шаблон должен быть: [RoutePrefix("api/v{version:apiVersion}/products")], как указано @ Sajid. Имейте в виду, что литерал v не является частью версии API, но распространен в методе управления версиями сегмента URL. version - это имя параметра маршрута, но может быть любым желаемым значением. apiVersion является ключом зарегистрированного ограничения маршрута, но вы можете изменить его в шаблоне, если вы также измените его в регистрации (см. Выпуск 1).

Выпуск 4

Аннотированный Версия API 1.0, но шаблон маршрута, похоже, подразумевает, что вы имели в виду 10.0. Вы можете использовать любое значение, которое хотите, но оно должно быть конгруэнтным. Если вы действительно хотите использовать 1.0, не забудьте изменить options.DefaultApiVersion, иначе вы получите исключение времени выполнения, потому что исходный API и ваш новый API будут считаться дубликатами, поскольку они имеют одинаковую версию API. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * [10] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}}}}. не рекомендуется смешивать стили маршрутизации. Это поддерживается, но это может сбивать с толку устранение неполадок и для сопровождающих. Я бы выбрал либо Прямая маршрутизация (он же Маршрутизация с атрибутом ), либо Маршрутизация на основе конвенций . В некоторых случаях их смешивание не работает, но они редки.

Это означает, что следует выбрать один из следующих вариантов:

Маршрутизация атрибутов
// setup (see Issue 1)
configuration.MapHttpAttributeRoutes( constraintResolver );

// old controller
[RoutePrefix("api/products")]
public class ProductsController : ApiController { }

// new controller; ControllerNameAttribute isn't need because it's not used
[ApiVersion("10.0")]
[RoutePrefix("api/v{version:apiVersion}/products")]
public class ProductsV1Controller : ApiController { }
Маршрутизация на основе конвенций
// setup
httpConfig.Routes.MapHttpRoute(
  name: "VersionedApi",
  routeTemplate: "api/v{apiVersion}/{controller}/{id}",
  defaults: new { id = RouteParameter.Optional },
  constraints: new { apiVersion = new ApiVersionRouteConstraint() });

httpConfig.Routes.MapHttpRoute(
  name: "DefaultApi",
  routeTemplate: "api/{controller}/{id}",
  defaults: new { id = RouteParameter.Optional },
  constraints: null);

// old controller
public class ProductsController : ApiController { }

// new controller
[ApiVersion("10.0")]
[ControllerName("Products")] // required because the convention-based name is "ProductsV1"
public class ProductsV1Controller : ApiController { }

Предупреждение. Вы можете смешивать эти стили, но устранение неполадок станет более сложным. Вам нужно обширное тестовое покрытие, чтобы убедиться, что все правильно. Одноразовое ручное тестирование может дать ложные срабатывания.


Надеюсь, это поможет

...