Web-API 版本控制不适用于默认版本
Web-API Versioning not working with Default version
我创建了一个带有版本控制的 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();
}
}
这里我的假设是如果我没有通过版本,默认情况下它会 select 版本 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。
{
"Message": "An error has occurred.",
"ExceptionMessage": "The index cannot be less than 0 or equal to or larger than the number of items in the collection.\r\n
Parameter
name: index\r\nActual value was 0.",
"ExceptionType": "System.ArgumentOutOfRangeException",
"StackTrace": " at
System.Web.Http.WebHost.Routing.HostedHttpRouteCollection.get_Item(Int32
index)\r\n at
Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.GetControllerName(HttpRequestMessage
request)\r\n at
Microsoft.Web.Http.Dispatcher.ControllerSelectionContext.<>c__DisplayClass6_0.<.ctor>b__0()\r\n
at System.Lazy1.CreateValue()\r\n at
System.Lazy
1.LazyInitValue()\r\n at System.Lazy`1.get_Value()\r\n
at
Microsoft.Web.Http.Dispatcher.ConventionRouteControllerSelector.SelectController(ControllerSelectionContext
context)\r\n at
Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.SelectController(HttpRequestMessage
request)\r\n at
System.Web.Http.Dispatcher.HttpControllerDispatcher.d__15.MoveNext()"
}
更新 1:
经过讨论和一些帮助,我可以确认此默认版本适用于常规路由。
使用属性路由时重现该问题。请检查我更新的代码。
- 我在 WebAPIConfig 文件中没有任何默认 API 路由。
- 我在控制器中更新路由前缀和路由
现在问题重现了。
您也可以通过组合常规和属性来重现该问题。
更新 2:
现在我注意到问题出在配置上。如果我直接在 Owin 启动 class 中添加路由配置,它工作正常。
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 class。所以我不知道它可能会影响任何其他功能
因此,如果我将 Owin 配置为在 Global.asax,它工作正常。
如果您不指定版本,则视为未版本化。在这种情况下,您必须设置 AssumeDefaultVersionWhenUnspecified
属性,如果没有另外说明,则假定默认版本 "1.0"
,如果指定 none:
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");
} );
这是一个已确认的错误,仅当在 vanilla IIS 实现(例如非 OWIN)上托管时才会发生。尽管 HttpRouteCollection 具有索引器,但 System.Web 定义的 HostedHttpRouteCollection 不支持它。不是抛出 NotSupportedException,而是抛出一个通用的 ArgumentOutOfRangeException。
有关详细信息,请参阅:https://github.com/Microsoft/aspnet-api-versioning/issues/428。
修复程序已在包版本 3.0.1 中可用。
我创建了一个带有版本控制的 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();
}
}
这里我的假设是如果我没有通过版本,默认情况下它会 select 版本 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。
{ "Message": "An error has occurred.",
"ExceptionMessage": "The index cannot be less than 0 or equal to or larger than the number of items in the collection.\r\n
Parameter name: index\r\nActual value was 0.",
"ExceptionType": "System.ArgumentOutOfRangeException",
"StackTrace": " at
System.Web.Http.WebHost.Routing.HostedHttpRouteCollection.get_Item(Int32 index)\r\n at Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.GetControllerName(HttpRequestMessage request)\r\n at Microsoft.Web.Http.Dispatcher.ControllerSelectionContext.<>c__DisplayClass6_0.<.ctor>b__0()\r\n at System.Lazy1.CreateValue()\r\n at System.Lazy
1.LazyInitValue()\r\n at System.Lazy`1.get_Value()\r\n
at Microsoft.Web.Http.Dispatcher.ConventionRouteControllerSelector.SelectController(ControllerSelectionContext context)\r\n at Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.SelectController(HttpRequestMessage request)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__15.MoveNext()" }
更新 1:
经过讨论和一些帮助,我可以确认此默认版本适用于常规路由。
使用属性路由时重现该问题。请检查我更新的代码。
- 我在 WebAPIConfig 文件中没有任何默认 API 路由。
- 我在控制器中更新路由前缀和路由
现在问题重现了。
您也可以通过组合常规和属性来重现该问题。
更新 2:
现在我注意到问题出在配置上。如果我直接在 Owin 启动 class 中添加路由配置,它工作正常。
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 class。所以我不知道它可能会影响任何其他功能
因此,如果我将 Owin 配置为在 Global.asax,它工作正常。
如果您不指定版本,则视为未版本化。在这种情况下,您必须设置 AssumeDefaultVersionWhenUnspecified
属性,如果没有另外说明,则假定默认版本 "1.0"
,如果指定 none:
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");
} );
这是一个已确认的错误,仅当在 vanilla IIS 实现(例如非 OWIN)上托管时才会发生。尽管 HttpRouteCollection 具有索引器,但 System.Web 定义的 HostedHttpRouteCollection 不支持它。不是抛出 NotSupportedException,而是抛出一个通用的 ArgumentOutOfRangeException。
有关详细信息,请参阅:https://github.com/Microsoft/aspnet-api-versioning/issues/428。
修复程序已在包版本 3.0.1 中可用。