我创建了一个带有版本控制的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.Lazy1.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:
经过讨论和一点帮助,我可以确认此默认版本适用于常规路由。
在使用属性路由时再现了该问题。请检查我更新的代码。
现在转载了该问题。
您还可以通过结合常规和属性来重现该问题。
现在我注意到问题出在配置上。如果我直接在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) ,它将正常工作。
答案 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)
您可以尝试设置默认版本号,并配置中间件以在未指定版本号时使用它。
services.AddApiVersioning(
o =>
{
o.AssumeDefaultVersionWhenUnspecified = true );
o.DefaultApiVersion = new ApiVersion("1.0");
} );