Reputation: 2030
I created one web API application with versioning. I am going to use Microsoft.AspNet.WebApi.Versioning
package to do that.
Webapi configuration:
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();
}
}
Here my assumption is if I didn't pass the version, by default it will select version 1.
Controller code:
[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);
}
}
If I test with http://localhost:10280/api/users/all?api-version=1.0
URL, it working fine. I am going to implement this feature in the existing project.
For backward compatibility, I tried http://localhost:10280/api/users/all
URL.
It gives me the following error with 500 as the status code.
{ "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()" }
Update 1:
After discussions and a bit of help, I can confirm that this default version works with conventional routing.
The issue reproduced while using attribute routing. Please check my updated code.
Now the issue reproduced.
You can also reproduce the issue with combining conventional and attribute.
Now I noticed that the issue lies in the configuration. If I add the routing configurations in the Owin startup class directly it working fine.
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);
}
}
It creates new HttpConfiugration other than using our existing WebAPIConfig class. So I don't know it may impact any other functionalities
So if i configure Owin to use webaPI instead of GlobalConfiguration.Configure(WebApiConfig.Register) in the Global.asax, it iw working fine.
Upvotes: 3
Views: 9603
Reputation: 4368
This is a confirmed bug that only occurs when hosting on a vanilla IIS implementation (e.g. non-OWIN). Despite the HttpRouteCollection having an indexer, the HostedHttpRouteCollection defined by System.Web does not support it. Instead of throwing NotSupportedException, a generic ArgumentOutOfRangeException is thrown.
For more details see: https://github.com/Microsoft/aspnet-api-versioning/issues/428.
The fix is in and is now available in package version 3.0.1.
Upvotes: 2
Reputation: 5624
You can try setting up the default version number and configure middleware to use it when version number is not specified.
Reference: Scott's blog on routing
services.AddApiVersioning(
o =>
{
o.AssumeDefaultVersionWhenUnspecified = true );
o.DefaultApiVersion = new ApiVersion("1.0");
} );
Upvotes: 0
Reputation: 23937
If you do not specify a version it is considered unversioned. In this case you have to set the AssumeDefaultVersionWhenUnspecified
property, which if not told otherwise, assumes a default version of "1.0"
, if none is specified:
config.AddApiVersioning(o => {
o.AssumeDefaultVersionWhenUnspecified = true;
});
This functionality is documented here: https://github.com/Microsoft/aspnet-api-versioning/wiki/Existing-Services-Quick-Start
Upvotes: 3