Web-API版本控制不适用于默认版本

时间:2019-01-02 08:37:23

标签: c# asp.net-web-api asp.net-web-api2 api-versioning

我创建了一个带有版本控制的Web 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   Microsoft.Web.Http.Dispatcher.ControllerSelectionContext。<> c__DisplayClass6_0。<。ctor> b__0()\ r \ n   位于System.Lazy 1.CreateValue()\r\n at System.Lazy 1.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   请求)\ r \ n   System.Web.Http.Dispatcher.HttpControllerDispatcher.d__15.MoveNext()“   }


更新1:

经过讨论和一点帮助,我可以确认此默认版本适用于常规路由。

在使用属性路由时再现了该问题。请检查我更新的代码。

  1. 我在WebAPIConfig文件中没有任何默认的API路由。
  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);

    }
}

除了使用我们现有的WebAPIConfig类之外,它还会创建新的 HttpConfiugration 。所以我不知道这可能会影响其他功能

因此,如果我将Owin配置为使用WebaPI代替Global.asax中的 GlobalConfiguration.Configure(WebApiConfig.Register) ,它将正常工作。

3 个答案:

答案 0 :(得分:2)

如果未指定版本,则将其视为未版本化。在这种情况下,您必须设置AssumeDefaultVersionWhenUnspecified属性,如果没有其他说明,则假定默认版本为"1.0"(如果未指定):

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

此功能记录在这里:https://github.com/Microsoft/aspnet-api-versioning/wiki/Existing-Services-Quick-Start

答案 1 :(得分:2)

这是一个已确认的错误,仅在使用普通IIS实现(例如非OWIN)托管时才会发生。尽管 HttpRouteCollection 具有索引器,但System.Web定义的 HostedHttpRouteCollection 不支持它。不会引发 NotSupportedException ,而是引发通用的 ArgumentOutOfRangeException

有关更多详细信息,请参见:https://github.com/Microsoft/aspnet-api-versioning/issues/428

此修补程序已经存在,并且现在可以在软件包版本3.0.1中使用。

答案 2 :(得分:0)

您可以尝试设置默认版本号,并配置中间件以在未指定版本号时使用它。

参考:Scott's blog on routing

services.AddApiVersioning(
    o =>
    {
        o.AssumeDefaultVersionWhenUnspecified = true );
        o.DefaultApiVersion = new ApiVersion("1.0");
    } );