Управление версиями Web-API не работает с версией по умолчанию

Я создал одно приложение веб-API с контролем версий. Я собираюсь использовать Microsoft.AspNet.WebApi.Versioning пакет, чтобы сделать это.

Конфигурация Webapi:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.AddApiVersioning(o => {
            o.AssumeDefaultVersionWhenUnspecified = true;
        });
        // Web API routes
        config.MapHttpAttributeRoutes();

    }
}

Здесь я предполагаю, что если я не прошел версию, по умолчанию будет выбрана версия 1.

Код контроллера:

[ApiVersion("1.0")]
[RoutePrefix("api/users")]
public class UserV1Controller : BaseController
{
    public UserV1Controller()
    {
    }

    [Route("all", Name = "UsersCollection")]
    public async Task<IHttpActionResult> GetAll()
    {
        var items = await UnitOfWork.Users.GetPaged(x => x.OrderBy(y => y.Id), 1, 20);
        //Add mapping to DTO 
        return Ok(items);
    }

}

Если я проверю с http://localhost:10280/api/users/all?api-version=1.0 URL, все работает нормально. Я собираюсь реализовать эту функцию в существующем проекте.

Для обратной совместимости я пробовал http://localhost:10280/api/users/all URL. Это дает мне следующую ошибку с 500 в качестве кода состояния.

{"Сообщение": "Произошла ошибка.",
"ExceptionMessage": "Индекс не может быть меньше 0 или равен или больше количества элементов в коллекции.\ R \n
Имя параметра: index\r\n Действительное значение было 0. ",
"ExceptionType": "System.ArgumentOutOfRangeException",
"StackTrace": "в
System.Web.Http.WebHost.Routing.HostedHttpRouteCollection.get_Item(индекс Int32)\r\n в Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.GetControllerName(запрос HttpRequestMessage)\r\n.ControllerSelectionContext.<> C__DisplayClass6_0. <. Ctor>b__0 ()\r\n в System.Lazy1.CreateValue()\r\n at System.Lazy1.LazyInitValue ()\r\n в System.Lazy`1.get_Value()\r\n
в Microsoft.Web.Http.Dispatcher.ConventionRouteControllerSelector.SelectController(контекст ControllerSelectionContext)\r\n в Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.SelectController(запрос HttpRequestMessage.ontrol.HD.d__15.MoveNext()" }


Обновление 1:

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

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

  1. У меня нет никакой API-маршрутизации по умолчанию в файле WebAPIConfig.
  2. Я обновляю Route Prefix и Route в контроллере

Теперь вопрос воспроизведен.

Вы также можете воспроизвести проблему с сочетанием обычного и атрибута.

Обновление 2:

Теперь я заметил, что проблема заключается в конфигурации. Если я добавлю конфигурации маршрутизации непосредственно в класс запуска Owin, он будет работать нормально.

    public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
        var configuration = new System.Web.Http.HttpConfiguration();
        var httpServer = new System.Web.Http.HttpServer(configuration);

        // reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
        configuration.AddApiVersioning(options =>
        {
            options.ReportApiVersions = true;
            options.AssumeDefaultVersionWhenUnspecified = true;
        });
        configuration.MapHttpAttributeRoutes();
        app.UseWebApi(httpServer);

    }
}

Он создает новую HttpConfiugration, отличную от использования нашего существующего класса WebAPIConfig. Так что я не знаю, может ли это повлиять на любые другие функции

Поэтому, если я настраиваю Овина на использование webaPI вместо GlobalConfiguration.Configure (WebApiConfig.Register) в Global.asax, он работает нормально.

3 ответа

Решение

Это подтвержденная ошибка, которая возникает только при размещении на ванильной реализации IIS (например, не OWIN). Несмотря на то, что HttpRouteCollection имеет индексатор, HostedHttpRouteCollection, определенный System.Web, не поддерживает его. Вместо исключения NotSupportedException генерируется универсальное ArgumentOutOfRangeException.

Для получения дополнительной информации см.: https://github.com/Microsoft/aspnet-api-versioning/issues/428.

Это исправление доступно и теперь доступно в пакете версии 3.0.1.

Если вы не укажете версию, она считается неверсионной. В этом случае вы должны установить AssumeDefaultVersionWhenUnspecified свойство, которое, если не указано иное, принимает версию по умолчанию "1.0", если ничего не указано:

config.AddApiVersioning(o => {
    o.AssumeDefaultVersionWhenUnspecified = true;
});

Эта функциональность описана здесь: https://github.com/Microsoft/aspnet-api-versioning/wiki/Existing-Services-Quick-Start

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

Ссылка: блог Скотта о маршрутизации

services.AddApiVersioning(
    o =>
    {
        o.AssumeDefaultVersionWhenUnspecified = true );
        o.DefaultApiVersion = new ApiVersion("1.0");
    } );
Другие вопросы по тегам